CF1100F Ivan and Burgers 记录
peterwuyihong · · 题解
题意:给定一个数列,每次询问一个区间中选取一些数的异或最大值,可以离线,
显然
思考一种神秘的对整体二分的做法。
对值域
现在是
现在是
#define maxn 500010
struct xxj{
#define Maxbit 21
#define _Tp int
_Tp p[Maxbit+1];
void insert(_Tp x){
if(!x)return;
for(int i=Maxbit;i+1;i--){
if(!(x>>i))continue;
if(!p[i]){p[i]=x;break;}
x^=p[i];
}
}
void clear(){memset(p,0,sizeof p);}
void insert(xxj h){for(int i=0;i<=Maxbit;i++)insert(h.p[i]);}
_Tp ask(){
_Tp ans=0;
for(int i=Maxbit;i+1;i--)
if((ans^p[i])>ans)ans^=p[i];
return ans;
}
}st[maxn];
int n,m;
int a[maxn];
struct prpr{
int l,r,id;
}q[maxn],tmpl[maxn],tmpr[maxn];
int Ans[maxn];
int work(xxj a,xxj b){
return a.insert(b),a.ask();
}
void solve(int l,int r,int L,int R){
if(L>R)return;
if(l==r){
for(int i=L;i<=R;i++)Ans[q[i].id]=a[l];
return;
}
int mid=(l+r)>>1;
st[mid].clear();
st[mid].insert(a[mid]);
for(int i=mid-1;i>=l;i--)st[i]=st[i+1],st[i].insert(a[i]);
for(int i=mid+1;i<=r;i++)st[i]=st[i-1],st[i].insert(a[i]);
int ll=0,rr=0;
for(int i=L;i<=R;i++){
if(q[i].r<mid)tmpl[++ll]=q[i];
else if(q[i].l>mid)tmpr[++rr]=q[i];
else Ans[q[i].id]=work(st[q[i].l],st[q[i].r]);
}
for(int i=1;i<=ll;i++)q[L+i-1]=tmpl[i];
for(int i=1;i<=rr;i++)q[L+ll+i-1]=tmpr[i];
solve(l,mid,L,L+ll-1);
solve(mid+1,r,L+ll,L+ll+rr-1);
}
signed main(){
#ifndef ONLINE_JUDGE
freopen("testdata.in","r",stdin);
#endif
cin>>n;for(int i=1;i<=n;i++)cin>>a[i];
cin>>m;for(int i=1;i<=m;i++)cin>>q[i].l>>q[i].r,q[i].id=i;
solve(1,n,1,m);
for(int i=1;i<=m;i++)cout<<Ans[i]<<endl;
#ifndef ONLINE_JUDGE
cerr<<endl<<(double)clock()/CLOCKS_PER_SEC;
#endif
}
合并时千万要把两个线性基合并起来再计算,不能不合并,like this
int ans=0;
for(int i=21;i+1;i--)if((ans^a.p[i])>ans)ans^=a.p[i];
for(int i=21;i+1;i--)if((ans^b.p[i])>ans)ans^=b.p[i];
return ans;