题意
给你一个数列,要求资瓷四个操作:
插入一个数
删除一个数
修改一个数
给出一个区间[l,r],设w为区间内第二大,问w与区间内元素异或的最大值。
n,m<=100000,元素大小小于2^20,强制在线
分析
都是套路题。直接外层替罪羊树内层trie就好了。注意要垃圾回收。
第一次写替罪羊树的删除操作。一开始想的是用删除节点的后继来替代删除节点,然后写的我一度开始怀疑人生。后来才知道替罪羊树的删除一般是伪删除,也就是在该节点上打上删除标记,然后不进行查找操作即可。在重建的时候再把那些节点去掉就好了。
代码
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
const int N=200005;
int n,m,sz,top,stack[N],rt,root[N],bin[25],a[5],R,n0;
struct tree{int l,r,s,size,del,fa,val,mx1,mx2;}t[N];
vector<int> p,q;
int read()
{
int x=0,f=1;char ch=getchar();
while (ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
struct Trie
{
int sz;
vector<int> re;
struct tree{int s,l,r;}t[30000005];
int newnode()
{
if (!re.size()) return ++sz;
else {int x=re.back();re.pop_back();return x;}
}
void reuse(int &d)
{
if (!d) return;
if (t[d].l) reuse(t[d].l);
if (t[d].r) reuse(t[d].r);
t[d].s=0;re.push_back(d);d=0;
}
void ins(int &d,int x,int y,int z)
{
if (!d) d=newnode();t[d].s+=z;
if (x==-1) return;
if (!(y&bin[x])) ins(t[d].l,x-1,y,z);
else ins(t[d].r,x-1,y,z);
}
int query(int d,int x,int y)
{
if (x==-1) return 0;
if (y&bin[x]) return t[t[d].l].s?query(t[d].l,x-1,y)+bin[x]:query(t[d].r,x-1,y);
else return t[t[d].r].s?query(t[d].r,x-1,y)+bin[x]:query(t[d].l,x-1,y);
}
}tr;
void updata(int d)
{
t[d].size=t[t[d].l].size+t[t[d].r].size+1;
t[d].s=t[t[d].l].s+t[t[d].r].s+1-t[d].del;
a[0]=t[d].val;a[1]=t[t[d].l].mx1;a[2]=t[t[d].l].mx2;
a[3]=t[t[d].r].mx1;a[4]=t[t[d].r].mx2;
sort(a,a+5);
t[d].mx1=a[4];t[d].mx2=a[3];
}
void build(int &d,int l,int r)
{
if (l>r) {d=0;return;}
int mid=(l+r)/2;d=stack[mid];
build(t[d].l,l,mid-1);if (t[d].l) t[t[d].l].fa=d;
build(t[d].r,mid+1,r);if (t[d].r) t[t[d].r].fa=d;
updata(d);
for (int i=l;i<=r;i++) tr.ins(root[d],19,t[stack[i]].val,1);
}
void dfs(int x)
{
tr.reuse(root[x]);
if (t[x].l) dfs(t[x].l);
if (!t[x].del) stack[++top]=x;
if (t[x].r) dfs(t[x].r);
}
void rebuild(int d)
{
int tmp=t[d].fa,op=(d==t[tmp].l?0:1);
top=0;dfs(d);build(d,1,top);
if (!tmp) {t[d].fa=0;rt=d;return;}
else
{
t[d].fa=tmp;
if (!op) t[tmp].l=d;
else t[tmp].r=d;
}
}
void ins(int &d,int x,int y)
{
if (!d) {d=++sz;t[d].val=y;tr.ins(root[d],19,y,1);updata(d);return;}
tr.ins(root[d],19,y,1);
if (t[d].del)
if (t[t[d].l].s>=x) ins(t[d].l,x,y),t[t[d].l].fa=d;
else ins(t[d].r,x-t[t[d].l].s,y),t[t[d].r].fa=d;
else if (t[t[d].l].s+1>=x) ins(t[d].l,x,y),t[t[d].l].fa=d;
else ins(t[d].r,x-t[t[d].l].s-1,y),t[t[d].r].fa=d;
updata(d);
if (t[d].size*0.75<max(t[t[d].l].size,t[t[d].r].size)) R=d;
}
int del(int &d,int x)
{
int w;
if (t[d].del) w=t[t[d].l].s>=x?del(t[d].l,x):del(t[d].r,x-t[t[d].l].s);
else if (t[t[d].l].s+1==x) {w=t[d].val;t[d].val=0;tr.ins(root[d],19,w,-1);t[d].del=1;updata(d);return w;}
else w=t[t[d].l].s+1>x?del(t[d].l,x):del(t[d].r,x-t[t[d].l].s-1);
tr.ins(root[d],19,w,-1);updata(d);
return w;
}
int modify(int &d,int x,int y)
{
int w;tr.ins(root[d],19,y,1);
if (t[d].del) w=t[t[d].l].s>=x?modify(t[d].l,x,y):modify(t[d].r,x-t[t[d].l].s,y);
else if (t[t[d].l].s+1==x) {w=t[d].val;t[d].val=y;tr.ins(root[d],19,w,-1);updata(d);return w;}
else w=t[t[d].l].s+1>x?modify(t[d].l,x,y):modify(t[d].r,x-t[t[d].l].s-1,y);
tr.ins(root[d],19,w,-1);updata(d);
return w;
}
void get(int d,int l,int r)
{
if (l>r) return;
if (l==1&&t[d].s==r) {p.push_back(d);return;}
int x=t[t[d].l].s,y=t[d].s;
if (!t[d].del&&l<=x+1&&r>=x+1) q.push_back(d);
get(t[d].l,l,min(x,r));get(t[d].r,max(1,l-x-1+t[d].del),r-x-1+t[d].del);
}
int solve(int l,int r)
{
p.clear();q.clear();get(rt,l,r);
int mx1=0,mx2=0;
for (int i=0;i<p.size();i++)
{
a[0]=mx1;a[1]=mx2;a[2]=t[p[i]].mx1;a[3]=t[p[i]].mx2;
sort(a,a+4);
mx1=a[3];mx2=a[2];
}
for (int i=0;i<q.size();i++)
if (t[q[i]].val>mx1) mx2=mx1,mx1=t[q[i]].val;
else if (t[q[i]].val>mx2) mx2=t[q[i]].val;
int ans=0;
for (int i=0;i<q.size();i++) ans=max(ans,mx2^t[q[i]].val);
for (int i=0;i<p.size();i++) ans=max(ans,tr.query(root[p[i]],19,mx2));
return ans;
}
int main()
{
bin[0]=1;
for (int i=1;i<=20;i++) bin[i]=bin[i-1]*2;
n=read();m=read();n0=n;sz=n;
for (int i=1;i<=n;i++)
{
int x=read();t[i].val=x;
}
for (int i=1;i<=n;i++) stack[++top]=i;
build(rt,1,n);
int ans=0;
while (m--)
{
char ch[2];scanf("%s",ch);
if (ch[0]=='I')
{
int x=(read()+ans)%n0+1,y=(read()+ans)%1048576;
ins(rt,x,y);n0++;
if (R) rebuild(R),R=0;
}
else if (ch[0]=='D')
{
int x=(read()+ans)%n0+1;
del(rt,x);n0--;
}
else if (ch[0]=='C')
{
int x=(read()+ans)%n0+1,y=(read()+ans)%1048576;
modify(rt,x,y);
}
else
{
int l=(read()+ans)%n0+1,r=(read()+ans)%n0+1;
printf("%d\n",ans=solve(l,r));
}
}
return 0;
}