bzoj 1901: Zju2112 Dynamic Rankings(离线树状数组+主席树)
2017-08-10 20:46
501 查看
1901: Zju2112 Dynamic Rankings
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 8144 Solved: 3378
[Submit][Status][Discuss]
Description
给定一个含有n个数的序列a[1],a[2],a[3]……a,程序必须回答这样的询问:对于给定的i,j,k,在a[i],a[i+1
],a[i+2]……a[j]中第k小的数是多少(1≤k≤j-i+1),并且,你可以改变一些a[i]的值,改变后,程序还能针对改
变后的a继续回答上面的问题。
Input
第一行一个数字N,代表测试组数对于每组数据第一行有两个正整数n(1≤n≤10000),m(1≤m≤10000)。
分别表示序列的长度和指令的个数。
第二行有n个数,表示a[1],a[2]……a
,这些数都小于10^9。
接下来的m行描述每条指令
每行的格式是下面两种格式中的一种。
Q i j k 或者 C i t
Q i j k (i,j,k是数字,1≤i≤j≤n, 1≤k≤j-i+1)
表示询问指令,询问a[i],a[i+1]……a[j]中第k小的数。
C i t (1≤i≤n,0≤t≤10^9)表示把a[i]改变成为t
Output
对于每一次询问,你都需要输出他的答案,每一个输出占单独的一行。Sample Input
15 3
3 2 1 4 7
Q 1 4 3
C 2 6
Q 2 5 3
Sample Output
36
回想一样不带修改的区间第K大
离散化+去重就不说了,n个点分别建立n棵线段树
第i棵线段树中保存前i个数中每个数出现的个数
这样每次查询区间[a, b]时直接将第b棵树减去第a-1棵树就可以logn查询了
但是要修改怎么办呢
……
先记录所有查询和修改,将一开始的数和后来修改出现的数离散化+去重
假设暴力修改第i个数的话,的确可以logn的复杂度修改当前树的结构,但是后面所有的树都必须修改
单次复杂度是O((n-i+1)*logn)的,肯定超时
……
想想简单的问题:
①给你n个数m次查询每次查一个区间[L, R]所有数之和
方法:直接记录前缀和然后答案就是sum[R]-sum[L-1]
②给你n个数m次查询每次查一个区间[L, R]所有数之和,但可以修改某个数的值
这个时候前缀和的方法就没用了,只能树状数组
……
其实查询区间第k大和带修改的区间第k大和上面那两个问题是一样的
对于只查询的,就前缀和两棵树相减
对于带修改的,就树状数组套主席树就好了
……
这样暴力修改第i个树的话,只用修改log(n-i+1)棵树,单次复杂度O(log(n-i+1)*logn),查询同理(也是logn)
总复杂度O(nlognlogn)
注意真实的题目并没有T组输入,是单实例
#include<stdio.h> #include<string.h> #include<algorithm> using namespace std; int n, m, size, cnt, c, d, b[20005], t[10005], a[10005], L[10005], R[10005], k[10005], low[10005], up[10005]; typedef struct { int l, r; int size; }Ctree; Ctree s[3000005]; int lowbit(int x){ return x&-x; } int Build(int l, int r); int Update(int root, int x, int val); int Query(int sum); int main(void) { char ch; int i, j, x; while(scanf("%d%d", &n, &m)!=EOF) { cnt = 0, size = n; for(i=1;i<=n;i++) { scanf("%d", &a[i]); b[i] = a[i]; } memset(R, -1, sizeof(R)); memset(s, 0, sizeof(s)); for(i=1;i<=m;i++) { scanf(" %c", &ch); if(ch=='Q') scanf("%d%d%d", &L[i], &R[i], &k[i]); else { scanf("%d%d", &L[i], &k[i]); b[++size] = k[i]; } } sort(b+1, b+size+1); size = unique(b+1, b+size+1)-(b+1); t[1] = Build(1, size); for(i=2;i<=n;i++) t[i] = t[1]; for(i=1;i<=n;i++) { x = lower_bound(b+1, b+size+1, a[i])-b; for(j=i;j<=n;j+=lowbit(j)) t[j] = Update(t[j], x, 1); } for(i=1;i<=m;i++) { if(R[i]==-1) { x = lower_bound(b+1, b+size+1, a[L[i]])-b; for(j=L[i];j<=n;j+=lowbit(j)) t[j] = Update(t[j], x, -1); a[L[i]] = k[i]; x = lower_bound(b+1, b+size+1, a[L[i]])-b; for(j=L[i];j<=n;j+=lowbit(j)) t[j] = Update(t[j], x, 1); } else { c = d = 0; for(j=L[i]-1;j>=1;j-=lowbit(j)) low[++c] = t[j]; for(j=R[i];j>=1;j-=lowbit(j)) up[++d] = t[j]; printf("%d\n", b[Query(k[i])]); } } } return 0; } int Build(int l, int r) { int m, root; root = ++cnt; m = (l+r)/2; s[root].size = 0; if(l==r) return root; s[root].l = Build(l, m); s[root].r = Build(m+1, r); return root; } int Update(int root, int x, int val) { int now, tmp, l, r, m; tmp = now = ++cnt; l = 1, r = size; while(l<r) { s[now].size = s[root].size+val; m = (l+r)/2; if(x<=m) { s[now].l = ++cnt; s[now].r = s[root].r; root = s[root].l; now = cnt; r = m; } else { s[now].l = s[root].l; s[now].r = ++cnt; root = s[root].r; now = cnt; l = m+1; } } s[now].size = s[root].size+val; return tmp; } int Query(int sum) { int l, r, m, i, now; l = 1, r = size; while(l<r) { now = 0; m = (l+r)/2; for(i=1;i<=d;i++) now += s[s[up[i]].l].size; for(i=1;i<=c;i++) now -= s[s[low[i]].l].size; if(now>=sum) { for(i=1;i<=d;i++) up[i] = s[up[i]].l; for(i=1;i<=c;i++) low[i] = s[low[i]].l; r = m; } else { sum -= now; for(i=1;i<=d;i++) up[i] = s[up[i]].r; for(i=1;i<=c;i++) low[i] = s[low[i]].r; l = m+1; } } return r; }
相关文章推荐
- Bzoj 1901 Zju2112 Dynamic Rankings(树状数组+主席树)
- 【bzoj1901】Zju2112 Dynamic Rankings 离散化+主席树+树状数组
- Bzoj 1901: Zju2112 Dynamic Rankings 主席树,可持久,树状数组,离散化
- 【BZOJ 1901】 Zju2112 Dynamic Rankings 主席树+树状数组
- 【BZOJ1901】Zju2112 Dynamic Rankings 主席树+树状数组
- bzoj 1901: Zju2112 Dynamic Rankings -- 主席树,树状数组,哈希
- [BZOJ1901]Zju2112 Dynamic Rankings(树状数组套主席树)
- BZOJ_P1901 [ZJU2112] Dynamic Rankings(树状数组+主席树)
- [bzoj1901][zoj2112][Dynamic Rankings] (整体二分+树状数组 or 动态开点线段树 or 主席树)
- 【BZOJ 1901】Zju2112 Dynamic Rankings &&【COGS 257】动态排名系统 树状数组套线段树
- [bzoj1901][Zju2112]Dynamic Rankings【树套树】【树状数组】【线段树】
- bzoj 1901: Zju2112 Dynamic Rankings (树状数组套线段树)
- 【BZOJ】1901: Zju2112 Dynamic Rankings(区间第k小+树状数组套主席树)
- [BZOJ 1901][ZOJ 2112]Dynamic Rankings(树状数组套主席树、动态区间第k大值查询)
- [离线+树状数组 || 主席树]BZOJ1878: [SDOI2009]HH的项链
- BZOJ 1901: Zju2112 Dynamic Rankings[带修改的主席树]【学习笔记】
- bzoj 1901 Zju2112 Dynamic Rankings(动态区间第k大,主席树)
- 【BZOJ】1901 Zju2112 Dynamic Rankings 树状数组+主席树
- [BZOJ]1901: Zju2112 Dynamic Rankings 主席树
- 【主席树】【bzoj 1901】: Zju2112 Dynamic Rankings