題目鏈接:Codeforces - Ivan and Burgers
讀題之後發現,比較顯然的做法就是線段樹維護線性基。(不過複雜度過高,一直沒卡過去)。
我們可以嘗試離線的做法、先按照右端點排序。
一次插入線性基當中,怎麼保證當前對答案異或的時候,這個基底是存在於[l,r]當中的呢?我們每次插入線性基的時候記錄一個時間戳即可。如果當前的時間戳大於等於L,就可以異或。
因爲我們是從前往後面掃,所以時間戳每次選最大的更新。
卡常失敗的代碼:
#pragma GCC optimize("-Ofast","-funroll-all-loops")
#include<bits/stdc++.h>
//#define int long long
using namespace std;
const int N=5e5+10;
int n,c[N],q;
char *fs,*ft,buf[1<<20];
#define gc() (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<20,stdin),fs==ft))?0:*fs++;
inline int read(){
int x=0,f=1; char ch=gc();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=gc();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=gc();}
return x*f;
}
struct lb{
int d[30];
inline void insert(int x){
for(int i=20;i>=0;i--) if(x>>i&1){
if(d[i]) x^=d[i];
else{d[i]=x; return ;}
}
}
inline void insert(lb &x){
for(int i=20;i>=0;i--) if(x.d[i]) insert(x.d[i]);
}
}t[N<<2],res;
void change(int p,int l,int r,int x,int v){
t[p].insert(v);
if(l==r) return ; int mid=l+r>>1;
if(x<=mid) change(p<<1,l,mid,x,v);
else change(p<<1|1,mid+1,r,x,v);
}
void ask(int p,int l,int r,int ql,int qr){
if(l==ql&&r==qr) return res.insert(t[p]),void();
int mid=l+r>>1;
if(qr<=mid) ask(p<<1,l,mid,ql,qr);
else if(ql>mid) ask(p<<1|1,mid+1,r,ql,qr);
else ask(p<<1,l,mid,ql,mid),ask(p<<1|1,mid+1,r,mid+1,qr);
}
inline int calc(){
int s=0;
for(int i=20;i>=0;i--) if((s^res.d[i])>s) s^=res.d[i];
return s;
}
signed main(){
n=read();
for(int i=1;i<=n;i++) c[i]=read(),change(1,1,n,i,c[i]);
q=read();
for(int i=1,l,r;i<=q;i++){
l=read(),r=read(); memset(res.d,0,sizeof res.d);
ask(1,1,n,l,r); printf("%d\n",calc());
}
return 0;
}
AC代碼:
#pragma GCC optimize("-Ofast","-funroll-all-loops")
#include<bits/stdc++.h>
//#define int long long
using namespace std;
const int N=5e5+10;
int n,d[25],dfn[25],c[N],q,res[N];
struct node{int l,r,id;}t[N];
char *fs,*ft,buf[1<<20];
#define gc() (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<20,stdin),fs==ft))?0:*fs++;
inline int read(){
int x=0,f=1; char ch=gc();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=gc();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=gc();}
return x*f;
}
int cmp(node a,node b){return a.r<b.r;}
inline void insert(int x,int id){
for(int i=20;i>=0;i--) if(x>>i&1){
if(!d[i]){d[i]=x; dfn[i]=id; return;}
if(dfn[i]<id) swap(d[i],x),swap(dfn[i],id);
x^=d[i];
}
}
inline int ask(int id){
int res=0;
for(int i=20;i>=0;i--) if(dfn[i]>=id&&(res^d[i])>res) res^=d[i];
return res;
}
signed main(){
n=read();
for(int i=1;i<=n;i++) c[i]=read();
q=read();
for(int i=1;i<=q;i++) t[i].l=read(),t[i].r=read(),t[i].id=i;
sort(t+1,t+1+q,cmp); int ed=1;
for(int i=1;i<=q;i++){
while(ed<=t[i].r) insert(c[ed],ed),ed++;
res[t[i].id]=ask(t[i].l);
}
for(int i=1;i<=q;i++) printf("%d\n",res[i]);
return 0;
}