bzoj 3065 带插入区间k小值
2017-02-12 09:47
381 查看
替罪羊树套权值线段树。
计数式垃圾回收。
复杂度nlog2^n。
写了半个冬令营。
计数式垃圾回收。
复杂度nlog2^n。
写了半个冬令营。
#include<iostream> #include<cstdio> #include<cstring> #include<vector> #include<algorithm> #define N 10000005 #define alpha 0.75 using namespace std; inline int read() { int x=0;char c=getchar(); while(c<'0'||c>'9')c=getchar(); while(c>='0'&&c<='9')x=x*10+c-'0',c=getchar(); return x; } int n; int v[70005],dfn[70005],root[70005],ch[70005][2],size[70005],num,zhi[70005],fa[70005]; int laji[N*2],sz; struct node { int l,r,sum; }a[N*2];int cnt; int lv[N*2]; int newnode() { if(!sz) { cnt++; lv[cnt]=1; return cnt; } int y=laji[sz--];lv[y]=1; return y; } void shan(int x) { if(!x)return; lv[x]--; if(!lv[x]) { shan(a[x].l);shan(a[x].r); a[x].l=a[x].r=0;a[x].sum=0; laji[++sz]=x; }return ; } void del(int x,int y,int l,int r,int z) { if(l==r) { a[x].sum=a[y].sum-1; return ; } int mid=(l+r)>>1; if(z<=mid) { a[x].l=newnode(); del(a[x].l,a[y].l,l,mid,z); a[x].r=a[y].r; lv[a[y].r]++; } else { a[x].r=newnode(); del(a[x].r,a[y].r,mid+1,r,z); a[x].l=a[y].l; lv[a[y].l]++; } a[x].sum=a[a[x].l].sum+a[a[x].r].sum; } void insert(int x,int y,int l,int r,int z) { if(l==r) { a[x].sum=a[y].sum+1; return ; } int mid=(l+r)>>1; if(z<=mid) { a[x].l=newnode(); insert(a[x].l,a[y].l,l,mid,z); a[x].r=a[y].r; lv[a[y].r]++; } else { a[x].r=newnode(); insert(a[x].r,a[y].r,mid+1,r,z); a[x].l=a[y].l; lv[a[y].l]++; } a[x].sum=a[a[x].l].sum+a[a[x].r].sum; } void merge(int x,int y,int z,int l,int r) { if(l==r) { a[x].sum=a[y].sum+a[z].sum; return ; } int mid=(l+r)>>1; if(!a[z].l) { if(a[y].l)a[x].l=a[y].l,lv[a[y].l]++; } else if(!a[y].l) { if(a[z].l)a[x].l=a[z].l,lv[a[z].l]++; } else { a[x].l=newnode(); merge(a[x].l,a[y].l,a[z].l,l,mid); } if(!a[z].r) { if(a[y].r)a[x].r=a[y].r,lv[a[y].r]++; } else if(!a[y].r) { if(a[z].r)a[x].r=a[z].r,lv[a[z].r]++; } else { a[x].r=newnode(); merge(a[x].r,a[y].r,a[z].r,mid+1,r); } a[x].sum=a[a[x].l].sum+a[a[x].r].sum; } void push_up(int x) { size[x]=size[ch[x][0]]+size[ch[x][1]]+1; return ; } int nw,zi[70005]; void build(int x,int l,int r) { size[x]=1;int mid=(l+r)>>1;zhi[x]=zi[mid]; if(l==r) { if(!root[x])root[x]=newnode(); insert(root[x],0,0,70000,zhi[x]); return ; } if(l!=mid) { ch[x][0]=dfn[++nw]; build(ch[x][0],l,mid-1); } ch[x][1]=dfn[++nw]; build(ch[x][1],mid+1,r); if(!root[x])root[x]=newnode(); merge(root[x],root[ch[x][0]],root[ch[x][1]],0,70000); int tmp=root[x]; root[x]=newnode(); insert(root[x],tmp,0,70000,zhi[x]); shan(tmp); push_up(x);fa[ch[x][0]]=x;fa[ch[x][1]]=x; } int rt,bd; void insert(int k,int x,int y) { int tmp=root[k];root[k]=newnode(); insert(root[k],tmp,0,70000,zhi[y]); shan(tmp); int l=ch[k][0]; if(size[l]+1>=x) { if(!ch[k][0]) { ch[k][0]=y; fa[y]=k;push_up(k); return ; } else insert(ch[k][0],x,y); } else { if(!ch[k][1]) { ch[k][1]=y; fa[y]=k;push_up(k); return ; } else insert(ch[k][1],x-size[l]-1,y); } push_up(k); if(max(size[ch[k][0]],size[ch[k][1]])>alpha*size[k])bd=k; } int dian[70005],top; void dfs(int x) { if(!x)return ; dfs(ch[x][0]); dian[++top]=x; zi[top]=zhi[x]; shan(root[x]);root[x]=0; dfs(ch[x][1]); ch[x][0]=ch[x][1]=0; fa[x]=0;size[x]=0; zhi[x]=0; return ; } void rebuild(int k) { top=0;int yy=fa[k]; dfs(k); for(int i=1;i<=top;i++)dfn[i]=dian[i]; nw=0; int tmp=dfn[++nw]; build(tmp,1,top); if(yy) { if(ch[yy][0]==k)ch[yy][0]=tmp; else ch[yy][1]=tmp; } } int tt; void gai(int x,int t1,int t2) { int l=ch[x][0]; int tmp=root[x];root[x]=newnode(); insert(root[x],tmp,0,70000,t2); shan(tmp); if(size[l]+1==t1) { tt=zhi[x]; tmp=root[x];root[x]=newnode(); del(root[x],tmp,0,70000,tt); zhi[x]=t2; return ; } if(size[l]+1>t1)gai(l,t1,t2); else gai(ch[x][1],t1-size[l]-1,t2); tmp=root[x];root[x]=newnode(); del(root[x],tmp,0,70000,tt); shan(tmp); } vector<int>t,q; void query(int x,int l,int r) { int L=size[ch[x][0]]; if(l==1&&size[x]==r) { t.push_back(root[x]);return ; } if(l<=L+1&&r>=L+1)q.push_back(zhi[x]); if(r<=L) { query(ch[x][0],l,r); } else if(l>L+1) { query(ch[x][1],l-L-1,r-L-1); } else { if(l<=L)query(ch[x][0],l,L); if(r>L+1)query(ch[x][1],1,r-L-1); } } int qur(int L,int R,int xx) { query(rt,L,R); int l=0,r=70000,s1=t.size(),s2=q.size(); while(l<r) { int mid=(l+r)>>1;int sum=0; for(int i=0;i<s1;i++)sum+=a[a[t[i]].l].sum; for(int i=0;i<s2;i++) { if(q[i]>=l&&q[i]<=mid)sum++; } if(xx<=sum) { for(int i=0;i<s1;i++)t[i]=a[t[i]].l; r=mid; } else { xx-=sum; for(int i=0;i<s1;i++)t[i]=a[t[i]].r; l=mid+1; } } t.clear();q.clear(); return l; } int main() { n=read(); for(int i=1;i<=n;i++)zi[i]=read(),dfn[i]=i; num=n;rt=1;nw=1; build(1,1,n); int q; scanf("%d",&q); char s[5]; int ans=0;int t1,t2,t3; for(int i=1;i<=q;i++) { if(cnt>19000000)return 0; scanf("%s",s); if(s[0]=='M') { t1=read();t2=read(); t1^=ans;t2^=ans; gai(rt,t1,t2); } else if(s[0]=='Q') { t1=read();t2=read();t3=read(); t1^=ans;t2^=ans;t3^=ans; ans=qur(t1,t2,t3); printf("%d\n",ans); } else { t1=read();t2=read(); t1^=ans;t2^=ans; num++;root[num]=newnode();zhi[num]=t2; size[num]=1;insert(root[num],0,0,70000,t2); bd=0; insert(rt,t1,num); if(bd)rebuild(bd); } } return 0; }
相关文章推荐
- bzoj 3065 带插入区间K小值 重量平衡treap套主席树
- BZOJ 3065 带插入区间K小值(sag套线段树)
- 【题解】BZOJ 3065: 带插入区间K小值——替罪羊树套线段树
- [BZOJ]3065: 带插入区间K小值 块状链表
- 【BZOJ】3065: 带插入区间K小值
- bzoj3065带插入区间K小值
- bzoj3065 带插入区间K小值(替罪羊树套动态开点线段树)
- 替罪羊树套线段树 【bzoj3065】 带插入区间k小值
- bzoj 3065 - 带插入区间第k大
- BZOJ 3065: 带插入区间K小值
- BZOJ 3065 带插入区间K小值
- BZOJ-3065 带插入区间K小值
- BZOJ 3065 带插入区间K小值 替罪羊树套线段树
- Bzoj3065 带插入区间K小值
- 【bzoj3065】: 带插入区间K小值 详解——替罪羊套函数式线段树
- BZOJ3065 带插入区间K小值
- [BZOJ]3065: 带插入区间K小值
- BZOJ 3065 带插入区间K小值
- BZOJ 3065: 带插入区间K小值 替罪羊树套权值线段树 详解
- BZOJ-3065 带插入区间K小值