题目分析
首先特殊商品显然可持久化trie树一波就行了。
至于非特殊商品呢?时间线段树套可持久化trie?
注意到本题没有要求强制在线,所以并不需要套呗。
把询问都落到时间线段树的区间上(用vector存),然后将所有添加商品事件都按照商店编号排序。
递归遍历时间线段树,遍历到一个区间(线段树的一个节点)时,将这个区间的所有添加商品事件建立可持久化trie树。然后处理这个节点上的所有询问。
代码
#include<bits/stdc++.h>
using namespace std;
#define RI register int
int read() {
int q=0;char ch=' ';
while(ch<'0'||ch>'9') ch=getchar();
while(ch>='0'&&ch<='9') q=q*10+ch-'0',ch=getchar();
return q;
}
const int N=100005,D=16;
int n,m,SZ,tim,Q;
int bin[17],rt[N],ans[N],st[N];
struct question{int l,r,tl,tr,x;}q[N];
struct event{int id,v,t;}e[N],e1[N],e2[N];
struct node{int s[2],sz;}tr[N*18];
bool cmp(event a,event b) {return a.id<b.id;}
void ins(int &x,int y,int num,int d) {
x=++SZ,tr[x]=tr[y],++tr[x].sz;
if(d==-1) return;
int t=((num&bin[d])==0?0:1);
ins(tr[x].s[t],tr[y].s[t],num,d-1);
}
int query(int x,int y,int num,int d) {
if(d==-1) return 0;
int t=((num&bin[d])==0?0:1);
if(tr[tr[y].s[t^1]].sz-tr[tr[x].s[t^1]].sz)
return query(tr[x].s[t^1],tr[y].s[t^1],num,d-1)+bin[d];
else return query(tr[x].s[t],tr[y].s[t],num,d-1);
}
vector<int> orz[N<<2];
void putdown(int l,int r,int s,int t,int i,int id) {
if(l>r) return;
if(l<=s&&t<=r) {orz[i].push_back(id);return;}
int mid=(s+t)>>1;
if(l<=mid) putdown(l,r,s,mid,i<<1,id);
if(mid+1<=r) putdown(l,r,mid+1,t,(i<<1)|1,id);
}
void work(int l,int r,int k) {
SZ=0;int top=0,js1=0,js2=0,mid=(l+r)>>1;
for(RI i=l;i<=r;++i)
st[++top]=e[i].id,ins(rt[top],rt[top-1],e[i].v,D);
for(RI i=0;i<orz[k].size();++i) {
int tmp=orz[k][i];
int l=lower_bound(st+1,st+1+top,q[tmp].l)-st;
int r=upper_bound(st+1,st+1+top,q[tmp].r)-st-1;
ans[tmp]=max(ans[tmp],query(rt[l-1],rt[r],q[tmp].x,D));
}
if(l==r) return;
for(RI i=l;i<=r;++i)
if(e[i].t<=mid) e1[++js1]=e[i];
else e2[++js2]=e[i];
for(RI i=1;i<=js1;++i) e[l+i-1]=e1[i];
for(RI i=1;i<=js2;++i) e[l+js1-1+i]=e2[i];
work(l,mid,k<<1),work(mid+1,r,(k<<1)|1);
}
int main()
{
int op,l,r,x,d;
n=read(),m=read();
bin[0]=1;for(RI i=1;i<=D;++i) bin[i]=bin[i-1]<<1;
for(RI i=1;i<=n;++i) x=read(),ins(rt[i],rt[i-1],x,D);
tim=1;
for(RI i=1;i<=m;++i) {
op=read();
if(op) {
l=read(),r=read(),x=read(),d=read();
q[++Q]=(question){l,r,max(1,tim-d+1),tim,x};
ans[Q]=query(rt[l-1],rt[r],x,D);
}
else e[++tim]=(event){read(),read(),tim};
}
for(RI i=1;i<=Q;++i) putdown(q[i].tl,q[i].tr,1,tim,1,i);
sort(e+1,e+1+tim,cmp);
work(1,tim,1);
for(RI i=1;i<=Q;++i) printf("%d\n",ans[i]);
return 0;
}