Bzoj 1901: Zju2112 Dynamic Rankings 树套树,线段树,平衡树,Treap

1901: Zju2112 Dynamic Rankings

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 6471  Solved: 2697
[Submit][Status][Discuss]

Description

给定一个含有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。

Input

对于每一次询问,你都需要输出他的答案,每一个输出占单独的一行。

Output

 

Sample Input

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

Sample Output

3
6

HINT

20%的数据中,m,n≤100; 40%的数据中,m,n≤1000; 100%的数据中,m,n≤10000。

Source

 区间线段树套Treap
上次写了个树状数组套主席树,这次复习一下区间线段树套Treap。
就是在询问时,去二分答案,然后判定小于等于二分的答案的个数是否有K个即可。
  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 #define MAXN 10010
  4 struct node
  5 {
  6     int left,right,val,size,rnd,count;
  7 }tree[MAXN*300];
  8 int tmp,SIZE,root[MAXN*300],a[MAXN];
  9 int read()
 10 {
 11     int s=0,fh=1;char ch=getchar();
 12     while(ch<'0'||ch>'9'){if(ch=='-')fh=-1;ch=getchar();}
 13     while(ch>='0'&&ch<='9'){s=s*10+(ch-'0');ch=getchar();}
 14     return s*fh;
 15 }
 16 void Update(int k){tree[k].size=tree[tree[k].left].size+tree[tree[k].right].size+tree[k].count;}
 17 void Lturn(int &k){int t=tree[k].right;tree[k].right=tree[t].left;tree[t].left=k;tree[t].size=tree[k].size;Update(k);k=t;}
 18 void Rturn(int &k){int t=tree[k].left;tree[k].left=tree[t].right;tree[t].right=k;tree[t].size=tree[k].size;Update(k);k=t;}
 19 void Insert(int &k,int x)
 20 {
 21     if(k==0)
 22     {
 23         SIZE++;k=SIZE;
 24         tree[k].val=x;tree[k].size=tree[k].count=1;tree[k].rnd=rand();
 25         return;
 26     }
 27     tree[k].size++;
 28     if(x==tree[k].val){tree[k].count++;return;}
 29     if(x<tree[k].val){Insert(tree[k].left,x);if(tree[tree[k].left].rnd<tree[k].rnd)Rturn(k);}
 30     else {Insert(tree[k].right,x);if(tree[tree[k].right].rnd<tree[k].rnd)Lturn(k);}
 31 }
 32 void Del(int &k,int x)
 33 {
 34     if(k==0)return;
 35     if(tree[k].val==x)
 36     {
 37         if(tree[k].count>1){tree[k].size--;tree[k].count--;return;}
 38         if(tree[k].left*tree[k].right==0)k=tree[k].left+tree[k].right;
 39         else if(tree[tree[k].left].rnd<tree[tree[k].right].rnd){Rturn(k);Del(k,x);}
 40         else {Lturn(k);Del(k,x);}
 41     }
 42     else if(x<tree[k].val){tree[k].size--;Del(tree[k].left,x);}
 43     else {tree[k].size--;Del(tree[k].right,x);}
 44 }
 45 void Find(int k,int x)
 46 {
 47     if(k==0)return;
 48     if(tree[k].val<=x){tmp+=(tree[tree[k].left].size+tree[k].count);Find(tree[k].right,x);}
 49     else Find(tree[k].left,x);
 50 }
 51 void Build(int k,int l,int r,int lr,int B)
 52 {
 53     Insert(root[k],B);
 54     if(l==r)return;
 55     int mid=(l+r)/2;
 56     if(lr<=mid)Build(k*2,l,mid,lr,B);
 57     else Build(k*2+1,mid+1,r,lr,B);
 58 }
 59 void Query(int k,int l,int r,int ql,int qr,int Q)
 60 {
 61     if(l==ql&&r==qr){Find(root[k],Q);return;}
 62     int mid=(l+r)/2;
 63     if(qr<=mid)Query(k*2,l,mid,ql,qr,Q);
 64     else if(ql>mid)Query(k*2+1,mid+1,r,ql,qr,Q);
 65     else {Query(k*2,l,mid,ql,mid,Q);Query(k*2+1,mid+1,r,mid+1,qr,Q);}
 66 }
 67 void Change(int k,int l,int r,int lr,int C1,int C2)
 68 {
 69     Del(root[k],C1);
 70     Insert(root[k],C2);
 71     if(l==r)return;
 72     int mid=(l+r)/2;
 73     if(lr<=mid)Change(k*2,l,mid,lr,C1,C2);
 74     else Change(k*2+1,mid+1,r,lr,C1,C2);
 75 }
 76 int main()
 77 {
 78     int n,m,i,l,r,k,L,R,mid,ii,ans;
 79     char zs;
 80     n=read();m=read();
 81     for(i=1;i<=n;i++)a[i]=read();
 82     for(i=1;i<=n;i++)Build(1,1,n,i,a[i]);
 83     for(i=1;i<=m;i++)
 84     {
 85         scanf("
%c",&zs);
 86         if(zs=='Q')
 87         {
 88             l=read();r=read();k=read();
 89             L=0;R=1000000000;ans=0;
 90             while(L<=R)
 91             {
 92                 mid=(L+R)/2;
 93                 tmp=0;
 94                 Query(1,1,n,l,r,mid);
 95                 if(tmp<k)L=mid+1;
 96                 else {ans=mid;R=mid-1;}
 97                 //else {ans=mid;break;}
 98                 //if(tmp>=k)R=mid-1;
 99                 //else L=mid+1;
100             }
101             //printf("%d
",L);
102             printf("%d
",ans);
103         }
104         else
105         {
106             ii=read();k=read();
107             Change(1,1,n,ii,a[ii],k);
108             a[ii]=k;
109         }
110     }
111     fclose(stdin);
112     fclose(stdout);
113     return 0;
114 }
原文地址:https://www.cnblogs.com/Var123/p/5336478.html