3196: Tyvj 1730 二逼平衡树
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 3033 Solved: 1201
[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可能为负数
Source
分析:
线段树套平衡树...
对于2操作就可以二分那个数字是区间第k大,然后查询当前数字再区间中的排名,不需要判断这个数字是否存在于区间中是因为所有排名合法的数字中最大的那个一定是答案...
比较忧伤的是写了线段树套Splay才知道我的线段树和Splay的常数有多大QAQ...
哎,没办法人帅自带大常数^_~...
1 #include<algorithm> 2 #include<iostream> 3 #include<cstring> 4 #include<cstdio> 5 //by NeighThorn 6 #define inf 1e8+8 7 using namespace std; 8 9 const int maxn=50000*70+5,maxm=50000+5; 10 11 int n,m,opt,a[maxm]; 12 13 int w[maxn],ls[maxn],rs[maxn],fa[maxn],cnt[maxn],siz[maxn],tot; 14 15 inline int read(void){ 16 char ch=getchar();int x=0,f=1; 17 while(!(ch>='0'&&ch<='9')){ 18 if(ch=='-') 19 f=-1; 20 ch=getchar(); 21 } 22 while(ch>='0'&&ch<='9') 23 x=x*10+ch-'0',ch=getchar(); 24 return x*f; 25 } 26 27 struct Splay{ 28 29 int root; 30 31 inline void zig(int x){ 32 int y=fa[x],tmp=siz[y]; 33 if(rs[x]) 34 ls[y]=rs[x],fa[rs[x]]=y,siz[y]=siz[y]-siz[x]+siz[rs[x]],siz[x]=tmp; 35 else 36 ls[y]=0,siz[y]=siz[y]-siz[x],siz[x]=tmp; 37 fa[x]=fa[y]; 38 if(fa[x]){ 39 if(ls[fa[x]]==y) 40 ls[fa[x]]=x; 41 else 42 rs[fa[x]]=x; 43 } 44 fa[y]=x,rs[x]=y; 45 } 46 47 inline void zag(int x){ 48 int y=fa[x],tmp=siz[y]; 49 if(ls[x]) 50 rs[y]=ls[x],fa[ls[x]]=y,siz[y]=siz[y]-siz[x]+siz[ls[x]],siz[x]=tmp; 51 else 52 rs[y]=0,siz[y]=siz[y]-siz[x],siz[x]=tmp; 53 fa[x]=fa[y]; 54 if(fa[x]){ 55 if(ls[fa[x]]==y) 56 ls[fa[x]]=x; 57 else 58 rs[fa[x]]=x; 59 } 60 fa[y]=x,ls[x]=y; 61 } 62 63 inline void splay(int x,int z){ 64 while(fa[x]!=z){ 65 int y=fa[x]; 66 if(fa[y]==z){ 67 if(ls[y]==x) 68 zig(x); 69 else 70 zag(x); 71 } 72 else{ 73 if(ls[fa[y]]==y){ 74 if(ls[y]==x) 75 zig(y),zig(x); 76 else 77 zag(x),zig(x); 78 } 79 else{ 80 if(rs[y]==x) 81 zag(y),zag(x); 82 else 83 zig(x),zag(x); 84 } 85 } 86 } 87 if(!z) 88 root=x; 89 } 90 91 inline void ins(int rt,int x){ 92 if(!rt) 93 w[++tot]=x,siz[tot]=cnt[tot]=1,root=tot; 94 else{ 95 while(!(w[rt]==x||(x<w[rt]&&!ls[rt])||(x>w[rt]&&!rs[rt]))){ 96 if(x<w[rt]) 97 siz[rt]++,rt=ls[rt]; 98 else if(x>w[rt]) 99 siz[rt]++,rt=rs[rt]; 100 } 101 if(w[rt]==x) 102 siz[rt]++,cnt[rt]++,splay(rt,0); 103 else if(x<w[rt]) 104 w[++tot]=x,siz[tot]=cnt[tot]=1,siz[rt]++,ls[rt]=tot,fa[tot]=rt,splay(tot,0); 105 else 106 w[++tot]=x,siz[tot]=cnt[tot]=1,siz[rt]++,rs[rt]=tot,fa[tot]=rt,splay(tot,0); 107 }/* 108 else if(w[rt]==x) 109 siz[rt]++,cnt[rt]++,splay(rt,0); 110 else if(x<w[rt]){ 111 if(!ls[rt]) 112 w[++tot]=x,siz[tot]=cnt[tot]=1,siz[rt]++,ls[rt]=tot,fa[tot]=rt,splay(tot,0); 113 else 114 siz[rt]++,ins(ls[rt],x); 115 } 116 else{ 117 if(!rs[rt]) 118 w[++tot]=x,siz[tot]=cnt[tot]=1,siz[rt]++,rs[rt]=tot,fa[tot]=rt,splay(tot,0); 119 else 120 siz[rt]++,ins(rs[rt],x); 121 }*/ 122 } 123 124 inline void del(int rt,int x){ 125 while(w[rt]!=x){ 126 if(x<w[rt]) 127 rt=ls[rt]; 128 else 129 rt=rs[rt]; 130 } 131 splay(rt,0); 132 if(cnt[rt]>1) 133 cnt[rt]--,siz[rt]--; 134 else{ 135 int l=ls[rt],r=rs[rt]; 136 if(!l) 137 ls[rt]=rs[rt]=fa[rt]=cnt[rt]=siz[rt]=0,fa[r]=0,root=r; 138 else{ 139 while(rs[l]) 140 l=rs[l]; 141 splay(l,rt);ls[rt]=rs[rt]=fa[rt]=cnt[rt]=siz[rt]=0;fa[r]=l,rs[l]=r,siz[l]+=siz[r];root=l,fa[l]=0; 142 } 143 } 144 } 145 146 inline int pre(int rt,int x){ 147 int res=-inf; 148 while(rt){ 149 if(w[rt]<x) 150 res=max(res,w[rt]),rt=rs[rt]; 151 else 152 rt=ls[rt]; 153 } 154 return res; 155 } 156 157 inline int suf(int rt,int x){ 158 int res=inf; 159 while(rt){ 160 if(w[rt]>x) 161 res=min(res,w[rt]),rt=ls[rt]; 162 else 163 rt=rs[rt]; 164 } 165 return res; 166 } 167 168 inline int rank(int rt,int x){ 169 while(w[rt]!=x){ 170 if(x<w[rt]) 171 rt=ls[rt]; 172 else 173 rt=rs[rt]; 174 } 175 splay(rt,0); 176 if(!ls[rt]) 177 return 1; 178 else 179 return siz[ls[rt]]+1; 180 } 181 182 inline int query(int rt,int x){ 183 if(!ls[rt]){ 184 if(cnt[rt]>=x){ 185 splay(rt,0); 186 return w[rt]; 187 } 188 else 189 return query(rs[rt],x-cnt[rt]); 190 } 191 else{ 192 if(siz[ls[rt]]>=x) 193 return query(ls[rt],x); 194 else if(siz[ls[rt]]+cnt[rt]>=x){ 195 splay(rt,0); 196 return w[rt]; 197 } 198 else 199 return query(rs[rt],x-siz[ls[rt]]-cnt[rt]); 200 } 201 } 202 203 }; 204 205 struct Tree{ 206 int l,r; 207 Splay s; 208 }tree[maxm*4]; 209 210 inline void build(int l,int r,int tr){ 211 tree[tr].l=l,tree[tr].r=r; 212 for(int i=l;i<=r;i++) 213 tree[tr].s.ins(tree[tr].s.root,a[i]); 214 if(l==r) 215 return; 216 int mid=(l+r)>>1; 217 build(l,mid,tr<<1);build(mid+1,r,tr<<1|1); 218 } 219 /* 220 inline void insert(int tr,int pos,int x){ 221 tree[tr].s.ins(tree[tr].s.root,x); 222 if(tree[tr].l==tree[tr].r) 223 return; 224 int mid=(tree[tr].l+tree[tr].r)>>1; 225 if(pos<=mid) 226 insert(tr<<1,pos,x); 227 else 228 insert(tr<<1|1,pos,x); 229 } 230 */ 231 inline int qryrank(int tr,int l,int r,int x){ 232 int lala; 233 if(tree[tr].l==l&&tree[tr].r==r) 234 return tree[tr].s.ins(tree[tr].s.root,x),lala=tree[tr].s.rank(tree[tr].s.root,x)-1,tree[tr].s.del(tree[tr].s.root,x),lala; 235 int mid=(tree[tr].l+tree[tr].r)>>1; 236 if(r<=mid) 237 return qryrank(tr<<1,l,r,x); 238 else if(l>mid) 239 return qryrank(tr<<1|1,l,r,x); 240 else 241 return qryrank(tr<<1,l,mid,x)+qryrank(tr<<1|1,mid+1,r,x); 242 } 243 244 inline void change(int tr,int pos,int x){ 245 tree[tr].s.del(tree[tr].s.root,a[pos]),tree[tr].s.ins(tree[tr].s.root,x); 246 if(tree[tr].l==tree[tr].r) 247 return; 248 int mid=(tree[tr].l+tree[tr].r)>>1; 249 if(pos<=mid) 250 change(tr<<1,pos,x); 251 else 252 change(tr<<1|1,pos,x); 253 } 254 255 inline int qrypre(int tr,int l,int r,int x){ 256 if(tree[tr].l==l&&tree[tr].r==r) 257 return tree[tr].s.pre(tree[tr].s.root,x); 258 int mid=(tree[tr].l+tree[tr].r)>>1; 259 if(r<=mid) 260 return qrypre(tr<<1,l,r,x); 261 else if(l>mid) 262 return qrypre(tr<<1|1,l,r,x); 263 else 264 return max(qrypre(tr<<1,l,mid,x),qrypre(tr<<1|1,mid+1,r,x)); 265 } 266 267 inline int qrysuf(int tr,int l,int r,int x){ 268 if(tree[tr].l==l&&tree[tr].r==r) 269 return tree[tr].s.suf(tree[tr].s.root,x); 270 int mid=(tree[tr].l+tree[tr].r)>>1; 271 if(r<=mid) 272 return qrysuf(tr<<1,l,r,x); 273 else if(l>mid) 274 return qrysuf(tr<<1|1,l,r,x); 275 else 276 return min(qrysuf(tr<<1,l,mid,x),qrysuf(tr<<1|1,mid+1,r,x)); 277 } 278 279 signed main(void){ 280 // freopen("3196.in","r",stdin); 281 // freopen("3196.out","w",stdout); 282 memset(ls,0,sizeof(ls)); 283 memset(rs,0,sizeof(rs)); 284 memset(fa,0,sizeof(fa)); 285 memset(cnt,0,sizeof(cnt)); 286 memset(siz,0,sizeof(siz)); 287 n=read(),m=read(); 288 for(int i=1;i<=n;i++) 289 a[i]=read();//,insert(1,i,a[i]); 290 build(1,n,1); 291 for(int i=1,l,r,x;i<=m;i++){ 292 opt=read(); 293 if(opt==1){ 294 l=read(),r=read(),x=read(); 295 printf("%d ",qryrank(1,l,r,x)+1); 296 } 297 else if(opt==2){ 298 l=read(),r=read(),x=read(); 299 int lef=1,rig=n,ans; 300 while(lef<=rig){ 301 int mid=(lef+rig)>>1,tmp=tree[1].s.query(tree[1].s.root,mid); 302 if(qryrank(1,l,r,tmp)<=x-1) 303 lef=mid+1,ans=tmp; 304 else 305 rig=mid-1; 306 } 307 printf("%d ",ans); 308 } 309 else if(opt==3){ 310 l=read(),x=read(); 311 change(1,l,x);a[l]=x; 312 } 313 else if(opt==4){ 314 l=read(),r=read(),x=read(); 315 printf("%d ",qrypre(1,l,r,x)); 316 } 317 else if(opt==5){ 318 l=read(),r=read(),x=read(); 319 printf("%d ",qrysuf(1,l,r,x)); 320 } 321 } 322 return 0; 323 }
by NeighThorn