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小值的主要内容,如果未能解决你的问题,请参考以下文章

[BZOJ3065]带插入区间K小值 解题报告 替罪羊树+值域线段树

Bzoj3065 带插入区间K小值

bzoj 3065 带插入区间k小值

BZOJ3065 带插入区间K小值

[BZOJ3065]带插入区间K小值

[bzoj3065] 带插入区间第k小值 [重量平衡树套线段树]