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
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
解题思路:
其实这道题最简单的做法有两个,第一个区间线段树套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\n",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\n",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\n",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\n",ans); 273 } 274 } 275 return 0; 276 }