码迷,mamicode.com
首页 > 其他好文 > 详细

BZOJ 3196 二逼平衡树

时间:2017-08-02 21:02:51      阅读:197      评论:0      收藏:0      [点我收藏+]

标签:ems   one   php   UI   src   print   标题   change   rip   

题面:

3196: Tyvj 1730 二逼平衡树

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 4026  Solved: 1551
[Submit][Status][Discuss]

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

HINT

1.n和m的数据范围:n,m<=50000

2.序列中每个数的数据范围:[0,1e8]

3.虽然原题没有,但事实上5操作的k可能为负数
 
线段树+splay(SBT死活调不过,还是splay大法吼!)
技术分享
  1 #include<stdio.h>
  2 using namespace std;
  3 #define maxn 60001
  4 #define INF 1<<30
  5 #define max(a,b) a>b?a:b
  6 #define min(a,b) a<b?a:b
  7 struct node
  8 {
  9     int w,size,count;
 10     node *fa,*son[2];
 11 }tree[maxn<<4],*stk[maxn<<4];
 12 int top,indx;
 13 int s[maxn],n,m;
 14 class Splay
 15 {
 16     private:
 17         node *newnode(int w,node *f)
 18         {
 19             node *t;
 20             if(top)t=stk[--top];
 21             else t=&tree[indx++];
 22             t->w=w;t->size=t->count=1;
 23             t->fa=f;t->son[0]=t->son[1]=NULL;
 24             return t;
 25         }
 26         inline void update(node *t)
 27         {
 28             if(t==NULL)
 29                 return ;
 30             t->size=t->count+size(t->son[0])+size(t->son[1]);
 31         }
 32         inline void freenode(node *t)
 33         {
 34             stk[top++]=t;
 35         }
 36         inline bool Son(node *f,node *t)
 37         {
 38             return f==NULL?0:f->son[1]==t;
 39         }
 40         inline int size(node *t)
 41         {
 42             return t==NULL?0:t->size;
 43         }
 44         inline void connect(node *f,node *t,bool flag)
 45         {
 46             if(f==NULL) root=t;
 47             else f->son[flag]=t;
 48             if(t!=NULL)t->fa=f;
 49         }
 50         void rotate(node *t)
 51         {
 52             node *f=t->fa;node *g=f->fa;
 53             bool a=Son(f,t),b=!a;
 54             connect(f,t->son[b],a);
 55             connect(g,t,Son(g,f));
 56             connect(t,f,b);
 57             update(f);update(t);
 58         }
 59         void splay(node *t,node *p)
 60         {
 61             if(t==NULL)return ;
 62             node *f,*g;
 63             while(t->fa!=p)
 64             {
 65                 f=t->fa;g=f->fa;
 66                 if(g==p)rotate(t);
 67                 else
 68                     if(Son(f,t)^Son(g,f))rotate(t),rotate(t);
 69                     else rotate(f),rotate(t);
 70             }
 71         }
 72         node *find(int w)
 73         {
 74             node *t=root;
 75             while(t!=NULL&&t->w!=w)t=t->son[w>=t->w];
 76             return splay(t,NULL),t;
 77         }
 78         node *insert(node *t,int w)
 79         {
 80             node *p=t->son[w>=t->w];
 81             if(p==NULL)p=t->son[w>=t->w]=newnode(w,t);
 82             else p=insert(p,w);
 83             return update(t),p;
 84         }
 85         void erase(node *t)
 86         {
 87             if(t->son[0]==NULL)
 88             {
 89                 connect(NULL,t->son[1],0);update(root);
 90             }
 91             else
 92                 if(t->son[1]==NULL)
 93                 {
 94                     connect(NULL,t->son[0],0);update(root);
 95                 }
 96                 else
 97                 {
 98                     node *p=t->son[0];
 99                     while(p->son[1]!=NULL)p=p->son[1];
100                     splay(p,t);connect(NULL,p,0);
101                     connect(p,t->son[1],1);update(root);
102                 }
103             freenode(t);
104         }
105         void erase(node *t,int k)
106         {
107             t->count-=k;
108             if(t->count<=0)erase(t);
109             else update(t);
110         }
111         public:
112             int l,r;node *root;
113             Splay(){}
114             void insert(int w)
115             {
116                 if(find(w)!=NULL)++root->count,update(root);
117                 else
118                     if(root==NULL)  root=newnode(w,NULL);
119                     else splay(insert(root,w),NULL);
120             }
121             void erase(int w)
122             {
123                 if(find(w)!=NULL)erase(root,1);
124             }
125             int pre(int w)
126             {
127                 int ans=-INF;
128                 for(node *t=root;t!=NULL;)
129                 {
130                     if(w>t->w)ans=max(ans,t->w);
131                     t=t->son[w>t->w];
132                 }
133                 return ans;
134             }
135             int suc(int w)
136             {
137                 int ans=INF;
138                 for(node *t=root;t!=NULL;)
139                 {
140                     if(w<t->w)ans=min(ans,t->w);
141                     t=t->son[w>=t->w];
142                 }
143                 return ans;
144             }
145             int RANK(node *t,int w)
146             {
147                 if(!t)return 0;
148                 if(t->w==w)return size(t->son[0]);
149                 if(t->w>w)return RANK(t->son[0],w);
150                 return size(t->son[0])+t->count+RANK(t->son[1],w);
151             }
152 }a[maxn<<2];
153 int ret;
154 void build(int id,int l,int r)
155 {
156      
157     a[id].l=l,a[id].r=r;
158     for(int i=l;i<=r;i++)
159         a[id].insert(s[i]);
160     if(l==r)
161         return ;
162     int mid=(l+r)>>1;
163     build(id<<1,l,mid);
164     build(id<<1|1,mid+1,r);
165 }
166 void change(int id,int p,int w)
167 {
168     a[id].erase(s[p]);a[id].insert(w);
169     if(a[id].l==a[id].r)return ;
170     int mid=(a[id].l+a[id].r)>>1;
171     if(p<=mid)change(id<<1,p,w);
172     else change(id<<1|1,p,w);
173 }
174 int query_pre(int id,int l,int r,int w)
175 {
176     if(l<=a[id].l&&a[id].r<=r)
177         return a[id].pre(w);
178     int mid=(a[id].l+a[id].r)>>1;
179     if(r<=mid)
180         return query_pre(id<<1,l,r,w);
181     else
182         if(l>mid)
183             return query_pre(id<<1|1,l,r,w);
184         else   
185             return max(query_pre(id<<1,l,mid,w),query_pre(id<<1|1,mid+1,r,w));
186 }
187 int query_suc(int id,int l,int r,int w)
188 {
189     if(l<=a[id].l&&a[id].r<=r)
190         return a[id].suc(w);
191     int mid=(a[id].l+a[id].r)>>1;
192     if(r<=mid)
193         return query_suc(id<<1,l,r,w);
194     else
195         if(l>mid)
196             return query_suc(id<<1|1,l,r,w);
197         else   
198             return min(query_suc(id<<1,l,mid,w),query_suc(id<<1|1,mid+1,r,w));
199 }
200 void query_rank(int id,int l,int r,int w)
201 {
202     if(l<=a[id].l&&a[id].r<=r)
203     {
204         ret+=a[id].RANK(a[id].root,w);
205         return ;
206     }
207     int mid=(a[id].l+a[id].r)>>1;
208     if(r<=mid)
209         query_rank(id<<1,l,r,w);
210     else
211         if(l>mid)
212             query_rank(id<<1|1,l,r,w);
213         else
214             query_rank(id<<1,l,mid,w),query_rank(id<<1|1,mid+1,r,w);
215 }
216 int query_kth(int l,int r,int k)
217 {
218     int L=0,R=1e9,mid,ans;
219     while(L!=R)
220     {
221         mid=(L+R)>>1;
222         ret=0;
223         query_rank(1,l,r,mid);
224         if(ret<k)
225             L=mid+1;
226         else
227             R=mid;
228     }
229     return L-1;
230 }
231 int main()
232 {
233     int op,l,r,k;
234     int x,y;
235     scanf("%d%d",&n,&m);
236     for(int i=1;i<=n;i++)
237         scanf("%d",&s[i]);
238     build(1,1,n);
239     for(int i=1;i<=m;i++)
240     {
241         scanf("%d",&op);
242         switch(op)
243         {
244             case 1:
245                 scanf("%d%d%d",&l,&r,&k);
246                 ret=0;
247                 query_rank(1,l,r,k);
248                 printf("%d\n",ret+1);
249                 break;
250             case 2:
251                 scanf("%d%d%d",&l,&r,&k);
252                 printf("%d\n",query_kth(l,r,k));
253                 break;
254             case 3:
255                 scanf("%d%d",&x,&y);
256                 change(1,x,y);
257                 s[x]=y;
258                 break;
259             case 4:
260                 scanf("%d%d%d",&l,&r,&k);
261                 printf("%d\n",query_pre(1,l,r,k));
262                 break;
263             case 5:
264                 scanf("%d%d%d",&l,&r,&k);
265                 printf("%d\n",query_suc(1,l,r,k));
266                 break;
267         }
268     }
269 }
BZOJ 3196

 

BZOJ 3196 二逼平衡树

标签:ems   one   php   UI   src   print   标题   change   rip   

原文地址:http://www.cnblogs.com/radioteletscope/p/7275937.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!