BZOJ 3196 二逼平衡树
Posted avancent
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ 3196 二逼平衡树相关的知识,希望对你有一定的参考价值。
题面:
3196: Tyvj 1730 二逼平衡树
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 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
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
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 二逼平衡树的主要内容,如果未能解决你的问题,请参考以下文章