BZOJ3196: Tyvj 1730 二逼平衡树(树套树)

Description

您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:
1.查询k在区间内的排名
2.查询区间内排名为k的值
3.修改某一位值上的数值
4.查询k在区间内的前驱(前驱定义为小于x,且最大的数)
5.查询k在区间内的后继(后继定义为大于x,且最小的数)

Input

第一行两个数 n,m 表示长度为n的有序序列和m个操作
第二行有n个数,表示有序序列
下面有m行,opt表示操作标号
若opt=1 则为操作1,之后有三个数l,r,k 表示查询k在区间[l,r]的排名
若opt=2 则为操作2,之后有三个数l,r,k 表示查询区间[l,r]内排名为k的数
若opt=3 则为操作3,之后有两个数pos,k 表示将pos位置的数修改为k
若opt=4 则为操作4,之后有三个数l,r,k 表示查询区间[l,r]内k的前驱
若opt=5 则为操作5,之后有三个数l,r,k 表示查询区间[l,r]内k的后继

Output

对于操作1,2,4,5各输出一行,表示查询结果

Sample Input

9 6
4 2 2 1 9 4 0 1 1
2 1 4 3
3 4 10
2 1 4 3
1 2 5 9
4 3 9 5
5 2 8 5

Sample Output

2
4
3
4
9

解题思路:

其实这道题最简单的做法有两个,第一个区间线段树套Treap,第二个是带修改主席树。

(整体二分CDQ打腻了打打树套树)

1.线段树套Treap代码:

  1 #include<ctime>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 #define lll spc<<1
  6 #define rrr spc<<1|1
  7 typedef long long lnt;
  8 const int N=1000000;
  9 const int oo=(int)(1e8);
 10 struct trent{
 11     int ls;
 12     int rs;
 13     int val;
 14     int num;
 15     int wgt;
 16     int rnd;
 17 }tr[N],stdtrent;
 18 int n,m;
 19 int ans;
 20 int top;
 21 int siz;
 22 int bin[N];
 23 int num[N];;
 24 int root[N];
 25 void pushup(int rt)
 26 {
 27     tr[rt].wgt=tr[rt].num+tr[tr[rt].ls].wgt+tr[tr[rt].rs].wgt;
 28     return ;
 29 }
 30 int newp(void)
 31 {
 32     if(top)
 33         return bin[top--];
 34     return ++siz;
 35 }
 36 void apply(int &rt)
 37 {
 38     rt=newp();
 39     tr[rt]=stdtrent;
 40     tr[rt].rnd=rand();
 41     tr[rt].num=1;
 42     return ;
 43 }
 44 void Del(int spc)
 45 {
 46     bin[++top]=spc;
 47     return ;
 48 }
 49 void lturn(int &rt)
 50 {
 51     int tmp=tr[rt].ls;
 52     tr[rt].ls=tr[tmp].rs;
 53     tr[tmp].rs=rt;
 54     pushup(rt);
 55     rt=tmp;
 56     pushup(rt);
 57     return ;
 58 }
 59 void rturn(int &rt)
 60 {
 61     int tmp=tr[rt].rs;
 62     tr[rt].rs=tr[tmp].ls;
 63     tr[tmp].ls=rt;
 64     pushup(rt);
 65     rt=tmp;
 66     pushup(rt);
 67     return ;
 68 }
 69 void Insert(int &rt,int v)
 70 {
 71     if(!rt)
 72     {
 73         apply(rt);
 74         tr[rt].val=v;
 75         pushup(rt);
 76         return ;
 77     }
 78     if(tr[rt].val==v)
 79     {
 80         tr[rt].num++;
 81     }else if(tr[rt].val>v)
 82     {
 83         Insert(tr[rt].ls,v);
 84         if(tr[tr[rt].ls].rnd<tr[rt].rnd)
 85             lturn(rt);
 86     }else{
 87         Insert(tr[rt].rs,v);
 88         if(tr[tr[rt].rs].rnd<tr[rt].rnd)
 89             rturn(rt);
 90     }
 91     pushup(rt);
 92     return ;
 93 }
 94 void Delete(int &rt,int v)
 95 {
 96     if(!rt)
 97         return ;
 98     if(tr[rt].val==v)
 99     {
100         if(tr[rt].num>1)
101             tr[rt].num--;
102         else{
103             if(!tr[rt].ls||!tr[rt].rs)
104             {
105                 Del(rt);
106                 rt=tr[rt].ls|tr[rt].rs;
107                 return ;
108             }else if(tr[tr[rt].ls].rnd<tr[tr[rt].rs].rnd)
109             {
110                 lturn(rt);
111                 Delete(tr[rt].rs,v);
112             }else{
113                 rturn(rt);
114                 Delete(tr[rt].ls,v);
115             }
116         }
117     }else if(tr[rt].val>v)
118         Delete(tr[rt].ls,v);
119     else
120         Delete(tr[rt].rs,v);
121     pushup(rt);
122     return ;
123 }
124 int Rank(int rt,int v)
125 {
126     if(!rt)
127         return 0;
128     if(tr[rt].val==v)
129         return tr[tr[rt].ls].wgt;
130     if(tr[rt].val>v)
131         return Rank(tr[rt].ls,v);
132     return Rank(tr[rt].rs,v)+tr[rt].num+tr[tr[rt].ls].wgt;
133 }
134 void Getpre(int rt,int v)
135 {
136     if(!rt)
137         return ;
138     if(tr[rt].val<v)
139     {
140         ans=std::max(ans,tr[rt].val);
141         Getpre(tr[rt].rs,v);
142     }else
143         Getpre(tr[rt].ls,v);
144     return ;
145 }
146 void Getnxt(int rt,int v)
147 {
148     if(!rt)
149         return ;
150     if(tr[rt].val>v)
151     {
152         ans=std::min(ans,tr[rt].val);
153         Getnxt(tr[rt].ls,v);
154     }else
155         Getnxt(tr[rt].rs,v);
156     return ;
157 }
158 void Build(int l,int r,int spc)
159 {
160     for(int i=l;i<=r;i++)
161         Insert(root[spc],num[i]);
162     if(l==r)
163         return ;
164     int mid=(l+r)>>1;
165     Build(l,mid,lll);
166     Build(mid+1,r,rrr);
167     return ;
168 }
169 int rank(int l,int r,int spc,int ll,int rr,int v)
170 {
171     if(ll>r||l>rr)
172         return 0;
173     if(ll<=l&&r<=rr)
174         return Rank(root[spc],v);
175     int mid=(l+r)>>1;
176     return rank(l,mid,lll,ll,rr,v)+rank(mid+1,r,rrr,ll,rr,v);
177 }
178 void update(int l,int r,int spc,int pos,int v,bool add)
179 {
180     if(add)
181         Insert(root[spc],v);
182     else
183         Delete(root[spc],v);
184     if(l==r)
185         return ;
186     int mid=(l+r)>>1;
187     if(pos<=mid)
188         update(l,mid,lll,pos,v,add);
189     else
190         update(mid+1,r,rrr,pos,v,add);
191     return ;
192 }
193 void getpre(int l,int r,int spc,int ll,int rr,int v)
194 {
195     if(l>rr||ll>r)
196         return ;
197     if(ll<=l&&r<=rr)
198     {
199         Getpre(root[spc],v);
200         return ;
201     }
202     int mid=(l+r)>>1;
203     getpre(l,mid,lll,ll,rr,v);
204     getpre(mid+1,r,rrr,ll,rr,v);
205     return ;
206 }
207 void getnxt(int l,int r,int spc,int ll,int rr,int v)
208 {
209     if(l>rr||ll>r)
210         return ;
211     if(ll<=l&&r<=rr)
212     {
213         Getnxt(root[spc],v);
214         return ;
215     }
216     int mid=(l+r)>>1;
217     getnxt(l,mid,lll,ll,rr,v);
218     getnxt(mid+1,r,rrr,ll,rr,v);
219     return ;
220 }
221 int main()
222 {
223     scanf("%d%d",&n,&m);
224     for(int i=1;i<=n;i++)
225         scanf("%d",&num[i]);
226     Build(1,n,1);
227     while(m--)
228     {
229         int cmd;
230         scanf("%d",&cmd);
231         if(cmd==1)
232         {
233             int l,r,x;
234             scanf("%d%d%d",&l,&r,&x);
235             ans=rank(1,n,1,l,r,x)+1;
236             printf("%d
",ans);
237         }else if(cmd==2)
238         {
239             int ll,rr,k;
240             scanf("%d%d%d",&ll,&rr,&k);
241             int l=-oo,r=oo;
242             while(l<=r)
243             {
244                 int mid=(l+r)>>1;
245                 if(rank(1,n,1,ll,rr,mid)<k)
246                 {
247                     ans=mid;
248                     l=mid+1;
249                 }else
250                     r=mid-1;
251             }
252             printf("%d
",ans);
253         }else if(cmd==3)
254         {
255             int pos,newv;
256             scanf("%d%d",&pos,&newv);
257             update(1,n,1,pos,num[pos],0);
258             num[pos]=newv;
259             update(1,n,1,pos,num[pos],1);
260         }else if(cmd==4)
261         {
262             int l,r,x;
263             scanf("%d%d%d",&l,&r,&x);
264             ans=-2147483647;
265             getpre(1,n,1,l,r,x);
266             printf("%d
",ans);
267         }else{
268             int l,r,x;
269             scanf("%d%d%d",&l,&r,&x);
270             ans=2147483647;
271             getnxt(1,n,1,l,r,x);
272             printf("%d
",ans);
273         }
274     }
275     return 0;
276 }
原文地址:https://www.cnblogs.com/blog-Dr-J/p/10116135.html