感觉这个线段树分治和整体二分几乎相同啊~
code:
#include <bits/stdc++.h>
#define MAX 100300
#define ll long long
#define lson now<<1
#define rson now<<1|1
#define setIO(s) freopen(s".in","r",stdin)
using namespace std;
struct Buy {int s,v,t; }q[MAX],tmp1[MAX],tmp2[MAX];
struct ASK {int l,r,tl,tr,x; }p[MAX];
bool cmp(Buy a,Buy b) { return a.s<b.s; }
int rt[MAX];
namespace Trie
{
struct Trie { int son[2],w; } t[MAX<<5];
int tot,rt[MAX];
void insert(int &x,int ff,int w,int now)
{
t[x=++tot]=t[ff]; t[x].w++;
if(now==-1) return;
bool c=(w&(1<<now));
insert(t[x].son[c],t[ff].son[c],w,now-1);
}
int Query(int l,int r,int w,int now)
{
if(now==-1) return 0;
bool c=w&(1<<now);
int tmp=t[t[r].son[c^1]].w-t[t[l].son[c^1]].w;
if(tmp) return Query(t[l].son[c^1],t[r].son[c^1],w,now-1)+(1<<now);
else return Query(t[l].son[c],t[r].son[c],w,now-1);
}
};
int n,m,ans[MAX];
vector<int>seg[MAX<<2];
int cnt1,cnt2;
void Modify(int now,int l,int r,int L,int R,int x)
{
if(L>R) return;
if(l>=L&&r<=R) { seg[now].push_back(x); return; }
int mid=(l+r)>>1;
if(L<=mid) Modify(lson,l,mid,L,R,x);
if(R>mid) Modify(rson,mid+1,r,L,R,x);
}
int S[MAX],top;
int find(int x)
{
int l=1,r=top,re=0;
while(l<=r)
{
int mid=(l+r)>>1;
if(S[mid]<=x) re=mid,l=mid+1;
else r=mid-1;
}
return re;
}
void sol(int now,int L,int R)
{
top=Trie::tot=0;
for(int i=L;i<=R;++i)
{
S[++top]=q[i].s;
Trie::insert(rt[top],rt[top-1],q[i].v,17);
}
for(int i=0;i<seg[now].size();++i)
{
int k=seg[now][i];
int l=find(p[k].l-1), r=find(p[k].r);
ans[k]=max(ans[k],Trie::Query(rt[l],rt[r],p[k].x,17));
}
}
void divide(int now,int l,int r,int L,int R)
{
if(L>R) return;
int mid=(l+r)>>1,t1=0,t2=0;
sol(now,L,R);
if(l==r) return;
for(int i=L;i<=R;++i)
{
if(q[i].t<=mid) tmp1[++t1]=q[i];
else tmp2[++t2]=q[i];
}
for(int i=1;i<=t1;++i) q[i+L-1]=tmp1[i];
for(int i=1;i<=t2;++i) q[i+L-1+t1]=tmp2[i];
divide(lson,l,mid,L,L+t1-1);
divide(rson,mid+1,r,L+t1,R);
}
int main()
{
// setIO("input");
int i,j;
scanf("%d%d",&n,&m);
for(i=1;i<=n;++i)
{
int x;
scanf("%d",&x);
Trie::insert(rt[i],rt[i-1],x,17);
}
for(i=1;i<=m;++i)
{
int opt;
scanf("%d",&opt);
if(!opt)
{
int s,v;
scanf("%d%d",&s,&v);
++cnt1;
q[cnt1]=(Buy){s,v,cnt1};
}
else
{
int l,r,x,d;
scanf("%d%d%d%d",&l,&r,&x,&d);
ans[++cnt2]=Trie::Query(rt[l-1],rt[r],x,17);
p[cnt2]=(ASK){l,r,max(1,cnt1-d+1),cnt1,x};
}
}
for(i=1;i<=cnt2;++i) Modify(1,1,cnt1,p[i].tl,p[i].tr,i);
sort(&q[1],&q[cnt1+1],cmp);
divide(1,1,cnt1,1,cnt1);
for(int i=1;i<=cnt2;++i) printf("%d\n",ans[i]);
return 0;
}