【bzoj1901】Zju2112 Dynamic Rankings

来源:互联网 发布:济南网络软件公司 编辑:程序博客网 时间:2024/05/07 03:09

题目描述:

给定一个含有n个数的序列a[1],a[2],a[3]……a[n],程序必须回答这样的询问:对于给定的i,j,k,在a[i],a[i+1],a[i+2]……a[j]中第k小的数是多少(1≤k≤j-i+1),并且,你可以改变一些a[i]的值,改变后,程序还能针对改变后的a继续回答上面的问题。你需要编一个这样的程序,从输入文件中读入序列a,然后读入一系列的指令,包括询问指令和修改指令。对于每一个询问指令,你必须输出正确的回答。 第一行有两个正整数n(1≤n≤10000),m(1≤m≤10000)。分别表示序列的长度和指令的个数。第二行有n个数,表示a[1],a[2]……a[n],这些数都小于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。

样例输入:

5 3
3 2 1 4 7
Q 1 4 3
C 2 6
Q 2 5 3


样例输出:

3
6


题解:
序列上的带修改的求区间第k小。树状数组套可持久化线段树。其实主席树的每一次Insert相当于一次线性变化(大雾),然后普通的主席树是按照上一个版本进行的变化,如果要修改的话那就用树状数组来维护这个线性变化,使得修改的复杂度从O(nlogn)降到了O((logn)^2)。


代码:

#include <cstdio>#include <cstring>#include <algorithm>#include <cmath>#ifdef WIN32#define LL "%I64d"#else#define LL "%lld"#endif#ifdef CT#define debug(...) printf(__VA_ARGS__)#define setfile() #else#define debug(...)#define filename ""#define setfile() freopen(filename".in","r",stdin);freopen(filename".out","w",stdout);#endif#define R register#define getc() (S==T&&(T=(S=B)+fread(B,1,1<<15,stdin),S==T)?EOF:*S++)#define dmax(_a, _b) ((_a) > (_b) ? (_a) : (_b))#define dmin(_a, _b) ((_a) < (_b) ? (_a) : (_b))#define cmax(_a, _b) (_a < (_b) ? _a = (_b) : 0)#define cmin(_a, _b) (_a > (_b) ? _a = (_b) : 0)char B[1<<15],*S=B,*T=B;inline int FastIn(){R char ch;R int cnt=0;R bool minus=0;while (ch=getc(),(ch < '0' || ch > '9') && ch != '-');ch == '-' ?minus=1:cnt=ch-'0';while (ch=getc(),ch >= '0' && ch <= '9') cnt = cnt * 10 + ch - '0';return minus?-cnt:cnt;}#define maxt 6200010#define maxn 10010const int oo = 1e9;int root[maxn], sum[maxt], ls[maxt], rs[maxt], tot, lcnt, rcnt, val[maxn], lr[maxn], rr[maxn];#define lowbit(_x) ((_x) & -(_x))int update (R int last, R int l, R int r, R int pre,R int c){R int mid = l + r >> 1, nw = ++tot;sum[nw] = sum[last] + c;if (l == r) return nw;if (pre > mid){ls[nw] = ls[last];rs[nw] = update(rs[last], mid + 1, r, pre, c);}else{rs[nw] = rs[last];ls[nw] = update(ls[last], l, mid, pre, c);}return nw;}inline int query(R int l, R int r, R int k){while (l < r){R int lsum = 0, rsum = 0, mid = l + r >> 1;for (R int i = 1; i <= lcnt; ++i)lsum += sum[ls[lr[i]]];for (R int i = 1; i <= rcnt; ++i)rsum += sum[ls[rr[i]]];if (rsum - lsum >= k){for (R int i = 1; i <= lcnt; ++i)lr[i] = ls[lr[i]];for (R int i = 1; i <= rcnt; ++i)rr[i] = ls[rr[i]];r = mid;}else{for (R int i = 1; i <= lcnt; ++i)lr[i] = rs[lr[i]];for (R int i = 1; i <= rcnt; ++i)rr[i] = rs[rr[i]];l = mid + 1;k -= (rsum - lsum);}}return l;}int main(){//setfile();R int n = FastIn(), q = FastIn();for (R int i = 1; i <= n; ++i){R int a = FastIn();for (R int j = i; j <= n; j += lowbit(j))root[j] = update(root[j], 0, oo, a, 1);val[i] = a;}for (R int i = 1; i <= q; ++i){R char cmd = getc();while (cmd!='Q'&&cmd!='C') cmd = getc();R int a = FastIn(), b = FastIn();if (cmd == 'Q'){R int k = FastIn();lcnt  = rcnt = 0;for (R int j = a - 1; j; j -= lowbit(j))lr[++lcnt] = root[j];for (R int j = b; j; j -= lowbit(j))rr[++rcnt] = root[j];printf("%d\n",query(0, oo, k) );}else{for (R int j = a; j <= n; j += lowbit(j))root[j] = update(root[j], 0, oo, val[a], -1);val[a] = b;for (R int j = a; j <= n; j += lowbit(j))root[j] = update(root[j], 0, oo, b, 1);}}return 0;}


0 0