【zoj2112】【线段树套平衡树】Dynamic Rankings

来源:互联网 发布:mac high sierra beta 编辑:程序博客网 时间:2024/05/16 11:06

很早以前就想做的一道题。本来想用主席树做的,无奈zoj的开的空间太小,用主席树不优化空间的话会MLE。

用树套树的话不算很麻烦,理解起来也很容易。建一颗线段树,然后对线段树的每个节点建立SBT

修改的时候递归对线段树的每个节点都删除平衡树中的那个值,再插入值。

由于平衡树只能求出数的排名,所以查询时二分一个数,查询排名,根据排名迭代出第k大的数。

代码:

#include<cstdio>#include<cstring>#define L ch[p][0]#define R ch[p][1]#define LL ch[ch[p][0]][0]#define RR ch[ch[p][1]][1]#define LR ch[ch[p][0]][1]#define RL ch[ch[p][1]][0]#define lson l,m,rt << 1#define rson m + 1,r,rt << 1 | 1using namespace std;const int maxn = 1000000 + 10;const int maxnum = 1000000000 + 10;int ch[maxn][2],sz[maxn],root[maxn];int num[maxn],val[maxn];int top = 0;int T;int n,m;void init(){freopen("zoj2112.in","r",stdin);freopen("zoj2112.out","w",stdout);}void Rotate(int &p,int f){int k = ch[p][!f];ch[p][!f] = ch[k][f];ch[k][f] = p;sz[k] = sz[p];sz[p] = sz[L] + sz[R] + 1;p = k;}void maintain(int &p,bool flag){if(p == 0)return;if(!flag){if(sz[LL] > sz[R])Rotate(p,1);else if(sz[LR] > sz[R])Rotate(L,0),Rotate(p,1);else return;}else{if(sz[RR] > sz[L])Rotate(p,0);else if(sz[RL] > sz[L])Rotate(R,1),Rotate(p,0);else return;}maintain(L,false);maintain(R,true);maintain(p,false);maintain(p,true);}void insert(int &p,int key){if(p == 0){p = ++top;ch[p][0] = ch[p][1] = 0;sz[p] = 1;val[p] = key;return;}sz[p]++;if(key < val[p])insert(ch[p][0],key);else insert(ch[p][1],key);maintain(p,!(key < val[p]));}int del(int &p,int key){sz[p]--;if((val[p] == key) || (key < val[p] && !ch[p][0]) || (key > val[p] && !ch[p][1])){int res = val[p];if(!ch[p][0] || !ch[p][1])p = ch[p][0] + ch[p][1];else val[p] = del(ch[p][0],val[p] + 1);return res;}else{if(key < val[p])return del(ch[p][0],key);else return del(ch[p][1],key);}}void build(int l,int r,int rt){root[rt] = 0;for(int i = l;i <= r;i++)insert(root[rt],num[i]);if(l == r)return;int m = (l + r) >> 1;build(lson);build(rson);}void update(int pos,int val,int ins,int l,int r,int rt){del(root[rt],val);insert(root[rt],ins);if(l == r)return;int m = (l + r) >> 1;if(pos <= m)update(pos,val,ins,lson);else update(pos,val,ins,rson);}int rank(int &p,int x){if(p == 0)return 0;if(val[p] > x)return rank(ch[p][0],x);else return sz[ch[p][0]] + 1 + rank(ch[p][1],x);}int calc(int a,int b,int x,int l,int r,int rt){if(a <= l && r <= b)return rank(root[rt],x);int m = (l + r) >> 1;int ret = 0;if(a <= m)ret += calc(a,b,x,lson);if(b > m)ret += calc(a,b,x,rson);return ret;}void readdata(){scanf("%d",&T);while(T--){top = 0;scanf("%d%d",&n,&m);for(int i = 1;i <= n;i++)scanf("%d",&num[i]);build(1,n,1);for(int i = 1;i <= m;i++){char op[4];scanf("%s",op);if(op[0] == 'C'){int a,b;scanf("%d%d",&a,&b);update(a,num[a],b,1,n,1);num[a] = b;}else{int a,b,k;scanf("%d%d%d",&a,&b,&k);int l = 0,r = maxnum;while(l < r){int m = (l + r) >> 1;if(calc(a,b,m,1,n,1) >= k)r = m;else l = m + 1;}printf("%d\n",r);}}}}int main(){init();readdata();return 0;}


原创粉丝点击