您的位置:首页 > 其它

bzoj 3065 带插入区间k小值

2017-02-12 09:47 381 查看
替罪羊树套权值线段树。

计数式垃圾回收。

复杂度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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: