[bzoj]-1901-Zju2112 Dynamic Rankings-可持久化线段树

来源:互联网 发布:web前端性能优化方案 编辑:程序博客网 时间:2024/04/27 20:44

动态查询区间第K大值,单点修改,树状数组套可持久化线段树,线段树中每个代表的相同区间的节点组成了一个树状数组,这样就可以logn的查询前缀和了。

写了好长时间,调了好长时间,毕竟蒟蒻

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#define maxn 110086using namespace std;struct node{int l, r, s;}t[maxn * 30];int n, m, num, root[maxn], a[maxn >> 1], b[maxn], dat[maxn >> 1][4], size, cnt, lc, rc, ln[maxn], rn[maxn];void build(int &x, int l, int r){x = ++cnt;t[x].s = 0;if (l == r)return ;int mid = (l + r) >> 1;build(t[x].l, l, mid);build(t[x].r, mid + 1, r);return ;}void update(int &x, int l, int r, int pos, int v){t[++cnt] = t[x];x = cnt;t[x].s += v;if (l == r)return ;int mid = (l + r) >> 1;if (pos <= mid)update(t[x].l, l, mid, pos, v);elseupdate(t[x].r, mid + 1, r, pos, v);return ;}void mutiupdate(int x, int pos, int v){while (x <= n){update(root[x], 1, num, pos, v);x += x & -x;}return ;}int query(int k){int l = 1, r = num, tl, tr;while (l != r){tl = tr = 0;for (int i = 1; i <= lc; i++)        tl += t[ t[ ln[i] ].l ].s;        for (int i = 1; i <= rc; i++)tr += t[ t[ rn[i] ].l ].s;        if (tr - tl >= k){            for (int i = 1; i <= lc; i++)ln[i] = t[ ln[i] ].l;            for (int i = 1; i <= rc; i++)rn[i] = t[ rn[i] ].l;            r = (l + r) >> 1;        }        else{        for (int i = 1; i <= lc; i++)            ln[i] = t[ ln[i] ].r;            for (int i = 1; i <= rc; i++)rn[i] = t[ rn[i] ].r;            l = (l + r >> 1) + 1;k -= tr - tl;         }}return l;}int getans(int l, int r, int k){lc = rc = 0;while (l){ln[++lc] = root[l];l -= l & -l;}while (r){rn[++rc] = root[r];r -= r & -r;}return query(k);}void solve(){    sort( b + 1, b + size + 1);    num = unique(b + 1, b + size + 1) - b - 1;    for (int i = 1; i <= n; i++) a[i] = lower_bound(b + 1, b + num + 1, a[i]) - b;    build(root[0], 1, num);    for (int i = 1; i <= n; i++)mutiupdate(i, a[i], 1);    for (int i = 1; i <= m; i++){        if(dat[i][0] == 0)printf("%d\n", b[ getans(dat[i][1] - 1, dat[i][2], dat[i][3]) ]);        else{            int pos = lower_bound(b + 1, b + num + 1, dat[i][2]) - b;            mutiupdate(dat[i][1], a[dat[i][1]], -1);            a[dat[i][1]] = pos;            mutiupdate(dat[i][1], a[dat[i][1]], 1);        }    }}int main(){scanf("%d %d", &n, &m);for (int i = 1; i <= n; i++){scanf("%d", &a[i]);b[++size] = a[i];}char cmd[3];for (int i = 1; i <= m; i++){scanf("%s", cmd);if (cmd[0] == 'C'){dat[i][0] = 1;scanf("%d %d",&dat[i][1], &dat[i][2]);b[++size] = dat[i][2];}else{dat[i][0] = 0;scanf("%d %d %d", &dat[i][1], &dat[i][2], &dat[i][3]);}}solve();return 0;}



0 0