bzoj 3065 带插入区间k小值
Posted SD_le
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj 3065 带插入区间k小值相关的知识,希望对你有一定的参考价值。
替罪羊树套权值线段树。
计数式垃圾回收。
复杂度nlog2^n。
写了半个冬令营。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<vector> 5 #include<algorithm> 6 #define N 10000005 7 #define alpha 0.75 8 using namespace std; 9 inline int read() 10 { 11 int x=0;char c=getchar(); 12 while(c<‘0‘||c>‘9‘)c=getchar(); 13 while(c>=‘0‘&&c<=‘9‘)x=x*10+c-‘0‘,c=getchar(); 14 return x; 15 } 16 int n; 17 int v[70005],dfn[70005],root[70005],ch[70005][2],size[70005],num,zhi[70005],fa[70005]; 18 int laji[N*2],sz; 19 struct node 20 { 21 int l,r,sum; 22 }a[N*2];int cnt; 23 int lv[N*2]; 24 int newnode() 25 { 26 if(!sz) 27 { 28 cnt++; 29 lv[cnt]=1; 30 return cnt; 31 } 32 int y=laji[sz--];lv[y]=1; 33 return y; 34 } 35 void shan(int x) 36 { 37 if(!x)return; 38 lv[x]--; 39 if(!lv[x]) 40 { 41 shan(a[x].l);shan(a[x].r); 42 a[x].l=a[x].r=0;a[x].sum=0; 43 laji[++sz]=x; 44 }return ; 45 } 46 void del(int x,int y,int l,int r,int z) 47 { 48 if(l==r) 49 { 50 a[x].sum=a[y].sum-1; 51 return ; 52 } 53 int mid=(l+r)>>1; 54 if(z<=mid) 55 { 56 a[x].l=newnode(); 57 del(a[x].l,a[y].l,l,mid,z); 58 a[x].r=a[y].r; 59 lv[a[y].r]++; 60 } 61 else 62 { 63 a[x].r=newnode(); 64 del(a[x].r,a[y].r,mid+1,r,z); 65 a[x].l=a[y].l; 66 lv[a[y].l]++; 67 } 68 a[x].sum=a[a[x].l].sum+a[a[x].r].sum; 69 } 70 void insert(int x,int y,int l,int r,int z) 71 { 72 if(l==r) 73 { 74 a[x].sum=a[y].sum+1; 75 return ; 76 } 77 int mid=(l+r)>>1; 78 if(z<=mid) 79 { 80 a[x].l=newnode(); 81 insert(a[x].l,a[y].l,l,mid,z); 82 a[x].r=a[y].r; 83 lv[a[y].r]++; 84 } 85 else 86 { 87 a[x].r=newnode(); 88 insert(a[x].r,a[y].r,mid+1,r,z); 89 a[x].l=a[y].l; 90 lv[a[y].l]++; 91 } 92 a[x].sum=a[a[x].l].sum+a[a[x].r].sum; 93 } 94 95 void merge(int x,int y,int z,int l,int r) 96 { 97 if(l==r) 98 { 99 a[x].sum=a[y].sum+a[z].sum; 100 return ; 101 } 102 int mid=(l+r)>>1; 103 if(!a[z].l) 104 { 105 if(a[y].l)a[x].l=a[y].l,lv[a[y].l]++; 106 } 107 else if(!a[y].l) 108 { 109 if(a[z].l)a[x].l=a[z].l,lv[a[z].l]++; 110 } 111 else 112 { 113 a[x].l=newnode(); 114 merge(a[x].l,a[y].l,a[z].l,l,mid); 115 } 116 if(!a[z].r) 117 { 118 if(a[y].r)a[x].r=a[y].r,lv[a[y].r]++; 119 } 120 else if(!a[y].r) 121 { 122 if(a[z].r)a[x].r=a[z].r,lv[a[z].r]++; 123 } 124 else 125 { 126 a[x].r=newnode(); 127 merge(a[x].r,a[y].r,a[z].r,mid+1,r); 128 } 129 a[x].sum=a[a[x].l].sum+a[a[x].r].sum; 130 } 131 void push_up(int x) 132 { 133 size[x]=size[ch[x][0]]+size[ch[x][1]]+1; 134 return ; 135 } 136 int nw,zi[70005]; 137 void build(int x,int l,int r) 138 { 139 size[x]=1;int mid=(l+r)>>1;zhi[x]=zi[mid]; 140 if(l==r) 141 { 142 if(!root[x])root[x]=newnode(); 143 insert(root[x],0,0,70000,zhi[x]); 144 return ; 145 } 146 if(l!=mid) 147 { 148 ch[x][0]=dfn[++nw]; 149 build(ch[x][0],l,mid-1); 150 } 151 ch[x][1]=dfn[++nw]; 152 build(ch[x][1],mid+1,r); 153 if(!root[x])root[x]=newnode(); 154 merge(root[x],root[ch[x][0]],root[ch[x][1]],0,70000); 155 int tmp=root[x]; 156 root[x]=newnode(); 157 insert(root[x],tmp,0,70000,zhi[x]); 158 shan(tmp); 159 push_up(x);fa[ch[x][0]]=x;fa[ch[x][1]]=x; 160 } 161 int rt,bd; 162 void insert(int k,int x,int y) 163 { 164 int tmp=root[k];root[k]=newnode(); 165 insert(root[k],tmp,0,70000,zhi[y]); 166 shan(tmp); 167 int l=ch[k][0]; 168 if(size[l]+1>=x) 169 { 170 if(!ch[k][0]) 171 { 172 ch[k][0]=y; 173 fa[y]=k;push_up(k); 174 return ; 175 } 176 else insert(ch[k][0],x,y); 177 } 178 else 179 { 180 if(!ch[k][1]) 181 { 182 ch[k][1]=y; 183 fa[y]=k;push_up(k); 184 return ; 185 } 186 else insert(ch[k][1],x-size[l]-1,y); 187 } 188 push_up(k); 189 if(max(size[ch[k][0]],size[ch[k][1]])>alpha*size[k])bd=k; 190 } 191 int dian[70005],top; 192 void dfs(int x) 193 { 194 if(!x)return ; 195 dfs(ch[x][0]); 196 dian[++top]=x; 197 zi[top]=zhi[x]; 198 shan(root[x]);root[x]=0; 199 dfs(ch[x][1]); 200 ch[x][0]=ch[x][1]=0; 201 fa[x]=0;size[x]=0; 202 zhi[x]=0; 203 return ; 204 } 205 void rebuild(int k) 206 { 207 top=0;int yy=fa[k]; 208 dfs(k); 209 for(int i=1;i<=top;i++)dfn[i]=dian[i]; 210 nw=0; 211 int tmp=dfn[++nw]; 212 build(tmp,1,top); 213 if(yy) 214 { 215 if(ch[yy][0]==k)ch[yy][0]=tmp; 216 else ch[yy][1]=tmp; 217 } 218 219 } 220 int tt; 221 void gai(int x,int t1,int t2) 222 { 223 int l=ch[x][0]; 224 int tmp=root[x];root[x]=newnode(); 225 insert(root[x],tmp,0,70000,t2); 226 shan(tmp); 227 if(size[l]+1==t1) 228 { 229 tt=zhi[x]; 230 tmp=root[x];root[x]=newnode(); 231 del(root[x],tmp,0,70000,tt); 232 zhi[x]=t2; 233 return ; 234 } 235 if(size[l]+1>t1)gai(l,t1,t2); 236 else gai(ch[x][1],t1-size[l]-1,t2); 237 tmp=root[x];root[x]=newnode(); 238 del(root[x],tmp,0,70000,tt); 239 shan(tmp); 240 } 241 vector<int>t,q; 242 void query(int x,int l,int r) 243 { 244 int L=size[ch[x][0]]; 245 if(l==1&&size[x]==r) 246 { 247 t.push_back(root[x]);return ; 248 } 249 if(l<=L+1&&r>=L+1)q.push_back(zhi[x]); 250 if(r<=L) 251 { 252 query(ch[x][0],l,r); 253 } 254 else if(l>L+1) 255 { 256 query(ch[x][1],l-L-1,r-L-1); 257 } 258 else 259 { 260 if(l<=L)query(ch[x][0],l,L); 261 if(r>L+1)query(ch[x][1],1,r-L-1); 262 } 263 } 264 int qur(int L,int R,int xx) 265 { 266 query(rt,L,R); 267 int l=0,r=70000,s1=t.size(),s2=q.size(); 268 while(l<r) 269 { 270 int mid=(l+r)>>1;int sum=0; 271 for(int i=0;i<s1;i++)sum+=a[a[t[i]].l].sum; 272 for(int i=0;i<s2;i++) 273 { 274 if(q[i]>=l&&q[i]<=mid)sum++; 275 } 276 if(xx<=sum) 277 { 278 for(int i=0;i<s1;i++)t[i]=a[t[i]].l; 279 r=mid; 280 } 281 else 282 { 283 xx-=sum; 284 for(int i=0;i<s1;i++)t[i]=a[t[i]].r; 285 l=mid+1; 286 } 287 } 288 t.clear();q.clear(); 289 return l; 290 } 291 int main() 292 { 293 n=read(); 294 for(int i=1;i<=n;i++)zi[i]=read(),dfn[i]=i; 295 num=n;rt=1;nw=1; 296 build(1,1,n); 297 int q; 298 scanf("%d",&q); 299 char s[5]; 300 int ans=0;int t1,t2,t3; 301 for(int i=1;i<=q;i++) 302 { 303 if(cnt>19000000)return 0; 304 scanf("%s",s); 305 if(s[0]==‘M‘) 306 { 307 t1=read();t2=read(); 308 t1^=ans;t2^=ans; 309 gai(rt,t1,t2); 310 } 311 else if(s[0]==‘Q‘) 312 { 313 t1=read();t2=read();t3=read(); 314 t1^=ans;t2^=ans;t3^=ans; 315 ans=qur(t1,t2,t3); 316 printf("%d\n",ans); 317 } 318 else 319 { 320 t1=read();t2=read(); 321 t1^=ans;t2^=ans; 322 num++;root[num]=newnode();zhi[num]=t2; 323 size[num]=1;insert(root[num],0,0,70000,t2); 324 bd=0; 325 insert(rt,t1,num); 326 if(bd)rebuild(bd); 327 } 328 } 329 return 0; 330 }
以上是关于bzoj 3065 带插入区间k小值的主要内容,如果未能解决你的问题,请参考以下文章