主席树+可持久化Trie
刚开始两者分开来写的,分别维护,太麻烦了,实际上开(1<<19)-1权值主席树可以完成同样的功能
实际上可持久化Trie本质和可持久化线段树思路是一样的。
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
using namespace std;
const int N=1000005;
int m,n;
int rt[N],tot;
struct aa
{
int lc,rc,l,r,size;
}a[N*10];
void build(int &u,int l,int r)
{
u=++tot;a[u].l=l,a[u].r=r;
if (l==r) return ;
int mid=(l+r)>>1;
build(a[u].lc,l,mid);
build(a[u].rc,mid+1,r);
}//
void insert(int old,int &young,int x)
{
young=++tot;
a[young]=a[old];
a[young].size++;
if (a[old].l==a[old].r) return ;
int mid=(a[old].l+a[old].r)>>1;
if (mid>=x) insert(a[old].lc,a[young].lc,x);
else insert(a[old].rc,a[young].rc,x);
}
int sum(int old,int young,int x)
{
if (a[old].l==a[old].r) return a[young].size-a[old].size;
int mid=(a[old].l+a[old].r)>>1;
if (mid>=x) return sum(a[old].lc,a[young].lc,x);
return a[a[young].lc].size-a[a[old].lc].size+sum(a[old].rc,a[young].rc,x);
}
int find(int old,int young,int k)
{
if (a[old].l==a[old].r) return a[old].l;
int tmp=a[a[young].lc].size-a[a[old].lc].size;
if (tmp>=k) return find(a[old].lc,a[young].lc,k);
return find(a[old].rc,a[young].rc,k-tmp);
}
int ans;
void work(int old,int young,int x,int dep)
{
if (dep==-1) return ;
int k=x&(1<<dep);if (k>0) k=1;
int tmp;
if (k==1)
{
tmp=a[a[young].lc].size-a[a[old].lc].size;
if (tmp>0) work(a[old].lc,a[young].lc,x,dep-1);
else ans+=(1<<dep),work(a[old].rc,a[young].rc,x,dep-1);
}
else
{
tmp=a[a[young].rc].size-a[a[old].rc].size;
if (tmp>0) ans+=(1<<dep),work(a[old].rc,a[young].rc,x,dep-1);
else work(a[old].lc,a[young].lc,x,dep-1);
}
}
int dep[N];
int main()
{
scanf("%d",&m);
build(rt[0],0,(1<<19)-1);
int opt,x,l,r;
for (int i=1;i<=m;i++)
{
scanf("%d",&opt);
switch(opt)
{
case 0:
n++;
scanf("%d",&x);
insert(rt[n-1],rt[n],x);
break;
case 1:
scanf("%d%d%d",&l,&r,&x);
ans=0;work(rt[l-1],rt[r],x,18);
printf("%d\n",ans);
break;
case 2:
scanf("%d",&x);
for (int j=n;j>=max(1,n-x+1);j--) tot-=20;
n-=x;
break;
case 3:
scanf("%d%d%d",&l,&r,&x);
printf("%d\n",sum(rt[l-1],rt[r],x));
break;
case 4:
scanf("%d%d%d",&l,&r,&x);
printf("%d\n",find(rt[l-1],rt[r],x));
break;
}
}
return 0;
}