HDU 6579
tags:线性基,优化
题意
让你在区间 \([l,r]\) 中选若干个数,使得异或和最大
支持末尾加入,区间查询,强在
题解
可以暴力维护区间的线性基,但是会超时
考虑维护每个点的前缀线性基,线性基里将靠右的数字尽可能放高位,就是存一个额外存一个位置 p,表示这个位上的数的位置,从高位到低位扫,如果当前位置大于这个位上的位置那么交换,然后就得到了一个靠右的数字尽可能在高位的线性基
然后对于询问 \([l,r]\) 在 \(r\) 的前缀线性基里找,只在位置大于等于 \(l\) 的位更新答案
#include<cstdio>
#include<algorithm>
#define int long long
#define rep(i,a,b) for(int i=(a);i<=(b);++i)
template<typename T>inline void rd(T&x){int fl=0,ch;while(ch=getchar(),ch<48||57<ch)fl^=!(ch^45);x=(ch&15);while(ch=getchar(),47<ch&&ch<58)x=x*10+(ch&15);if(fl)x=-x;}
template<typename T>inline void pt(T x){if(x<0)putchar('-'),x=-x;if(x>9)pt(x/10);putchar(x%10+48);}
template<typename T>inline void pt(T x,int ch){pt(x),putchar(ch);}
template<typename T>inline T max(const T&x,const T&y){return x<y?y:x;}
template<typename T>inline T min(const T&x,const T&y){return x<y?x:y;}
const int N=500005;
int T,n,m,a[N],b[N][31],p[N][31];
void ins(int*b,int*p,int x,int pos){
for(int i=30;~i;--i)if(x>>i&1){
if(!b[i]){
b[i]=x;
p[i]=pos;
break;
}else{
if(pos>p[i]){
std::swap(b[i],x);
std::swap(p[i],pos);
}
x^=b[i];
}
}
}
int qry(int*b,int*p,int pos){
int res=0;
for(int i=30;~i;--i)if(p[i]>=pos&&(res^b[i])>res)res^=b[i];
return res;
}
signed main(){
rd(T);
while(T--){
int n,m;rd(n),rd(m);
rep(i,1,n){
rd(a[i]);
memcpy(b[i],b[i-1],sizeof(b[i]));
memcpy(p[i],p[i-1],sizeof(p[i]));
ins(b[i],p[i],a[i],i);
}
int lst=0;
while(m--){
int op;rd(op);
if(op==0){
int l,r;rd(l),rd(r);
l=(l^lst)%n+1,r=(r^lst)%n+1;
if(r<l)l^=r^=l^=r;
pt(lst=qry(b[r],p[r],l),'\n');
}else{
rd(a[++n]);a[n]^=lst;
memcpy(b[n],b[n-1],sizeof(b[n]));
memcpy(p[n],p[n-1],sizeof(p[n]));
ins(b[n],p[n],a[n],n);
}
}
}
return 0;
}