BZOJ1901 Zju2112 Dynamic Rankings 【树状数组套主席树】
2018-01-20 09:22
387 查看
题目
给定一个含有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继续回答上面的问题。
输入格式
第一行有两个正整数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
m,n≤10000
输出格式
对于每一次询问,你都需要输出他的答案,每一个输出占单独的一行。
输入样例
5 3
3 2 1 4 7
Q 1 4 3
C 2 6
Q 2 5 3
输出样例
3
6
题解
很裸的板
树状数组维护区间,主席树维护树状数组每个节点权值信息
【debug弄得要死,调用时(1,tot)写成了(l,r) QAQ】
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define REP(i,n) for (int i = 1; i <= (n); i++) #define lbt(x) (x & -x) using namespace std; const int maxn = 10005,maxm = 10000005,INF = 1000000000; inline int read(){ int out = 0,flag = 1; char c = getchar(); while (c < 48 || c > 57) {if (c == '-') flag = -1; c = getchar();} while (c >= 48 && c <= 57) {out = (out << 3) + (out << 1) + c - '0'; c = getchar();} return out * flag; } int rt[maxn],A[maxn],B[2 * maxn],n,m,tot = 1,siz,N; int sum[maxm],ls[maxm],rs[maxm],a[2][20]; struct Que{int opt,l,r,k;}Q[maxn]; int getn(int x){ int l = 1,r = tot,mid; while (l <= r){ mid = l + r >> 1; if (B[mid] < x) l = mid + 1; else r = mid - 1; } return l; } void update(int& u,int l,int r,int pos,int v){ if (!u) u = ++siz; sum[u] += v; if (l == r) return; int mid = l + r >> 1; if (mid >= pos) update(ls[u],l,mid,pos,v); else update(rs[u],mid + 1,r,pos,v); } int query(int l,int r,int k){ if (l == r) return l; int mid = l + r >> 1,t = 0; for (int i = 1; i <= a[0][0]; i++) t += sum[ls[a[0][i]]]; for (int i = 1; i <= a[1][0]; i++) t -= sum[ls[a[1][i]]]; if (t >= k){ for (int i = 1; i <= a[0][0]; i++) a[0][i] = ls[a[0][i]]; for (int i = 1; i <= a[1][0]; i++) a[1][i] = ls[a[1][i]]; return query(l,mid,k); }else { for (int i = 1; i <= a[0][0]; i++) a[0][i] = rs[a[0][i]]; for (int i = 1; i <= a[1][0]; i++) a[1][i] = rs[a[1][i]]; return query(mid + 1,r,k - t); } } void add(int u,int x,int v){while (u <= n) update(rt[u],1,tot,x,v),u += lbt(u);} int solve(int l,int r,int k){ a[0][0] = a[1][0] = 0; for (int i = r; i; i -= lbt(i)) a[0][++a[0][0]] = rt[i]; for (int i = l - 1; i; i -= lbt(i)) a[1][++a[1][0]] = rt[i]; return query(1,tot,k); } int main(){ n = read(); m = read(); char c; REP(i,n) A[i] = B[++N] = read(); REP(i,m){ c = getchar(); while (c != 'Q' && c != 'C') c = getchar(); if (c == 'Q') Q[i].opt = 0,Q[i].l = read(),Q[i].r = read(),Q[i].k = read(); else Q[i].opt = 1,Q[i].l = read(),Q[i].k = B[++N] = read(); } sort(B + 1,B + 1 + N); for (int i = 2; i <= N; i++) if (B[i] != B[tot]) B[++tot] = B[i]; REP(i,n) A[i] = getn(A[i]),add(i,A[i],1); REP(i,m){ if (!Q[i].opt) printf("%d\n",B[solve(Q[i].l,Q[i].r,Q[i].k)]); else{ Q[i].k = getn(Q[i].k); add(Q[i].l,A[Q[i].l],-1); A[Q[i].l] = Q[i].k; add(Q[i].l,A[Q[i].l],1); } } return 0; }
相关文章推荐
- 【BZOJ1901】Zju2112 Dynamic Rankings【树状数组套主席树 / 整体二分】
- BZOJ 1901: Zju2112 Dynamic Rankings 树状数组套主席树
- BZOJ 1901: Zju2112 Dynamic Rankings( 树状数组套主席树 )
- BZOJ 1901 Zju2112 Dynamic Rankings ——树状数组套主席树
- 【bzoj1901】Zju2112 Dynamic Rankings 树状数组套主席树
- 【BZOJ 1901】【Zju 2112】 Dynamic Rankings 动态K值 树状数组套主席树模板题
- BZOJ_1901_&_ZJU_2112_Dynamic_Rankings_(主席树+树状数组/线段树+(Treap/Splay))
- [bzoj1901][Zju2112]Dynamic Rankings_主席树
- 【BZOJ】1901: Zju2112 Dynamic Rankings(区间第k小+树状数组套主席树)
- 主席树初探--BZOJ1901: Zju2112 Dynamic Rankings
- [BZOJ]1901: Zju2112 Dynamic Rankings 主席树
- [BZOJ1901]Zju2112 Dynamic Rankings(树状数组套主席树)
- bzoj1901 Zju2112 Dynamic Rankings(主席树+树状数组)
- 【主席树】【bzoj 1901】: Zju2112 Dynamic Rankings
- Bzoj 1901 Zju2112 Dynamic Rankings(树状数组+主席树)
- 【BZOJ】1901 Zju2112 Dynamic Rankings 树状数组+主席树
- 【BZOJ 1901】 Zju2112 Dynamic Rankings 主席树+树状数组
- bzoj 1901: Zju2112 Dynamic Rankings(带修改的区间第k大,树状数组+主席树)
- Bzoj 1901: Zju2112 Dynamic Rankings 主席树,可持久,树状数组,离散化
- bzoj 1901: Zju2112 Dynamic Rankings(离线树状数组+主席树)