正解线性基。
总的来说和lca一样,预处理出f[x][i]为x一直到x向根走 $ 2^i $ 步的合并线性基,
那么可以和lca一样进行处理和合并,从而得到路径的线性基。
再进行操作即可。
不过我没有控memset,卡常卡了半天都没过,最后改了下memset就A了。
卡常真的恶心。
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #define clear(a) memset((a).d,0,sizeof((a).d)) using namespace std; typedef long long ll; const int maxn=2e4+5; ll n,q,x,y; ll w[maxn]; char xB[(1<<15)+10],*xS=xB,*xT=xB; #define gtc (xS==xT&&(xT=(xS=xB)+fread(xB,1,1<<15,stdin),xS==xT)?0:*xS++) inline void read(ll &x){ register char ch=gtc; for(x=0;ch<'0'||ch>'9';ch=gtc); for(;ch>='0'&&ch<='9';x=(x<<1)+(x<<3)+ch-'0',ch=gtc); } inline void print(ll x) { if(x<0) {putchar('-'); x=-x;} if(x>9) print(x/10); putchar(x%10+48); return; } struct Road{ int tot,t[maxn<<1],nxt[maxn<<1],first[maxn]; void add(int x,int y) { t[++tot]=y; nxt[tot]=first[x]; first[x]=tot; } }eage; struct Least_Common_Ancetor{ struct line_bsis{ ll d[63]; void insert(ll x) { for(register int i=61;i>=0;i--) if((x>>i)&1) { if(!d[i]) {d[i]=x;break;} x^=d[i]; } } ll ma() { ll ans=0; for(register int i=61;i>=0;i--) if((ans^d[i])>ans) ans^=d[i]; return ans; } }lb[maxn][30],own[maxn],tmp,r; int p,d[maxn],f[maxn][30]; inline line_bsis merge(const line_bsis &a,const line_bsis &b) { clear(r); for(register int i=60;i>=0;i--) { if(a.d[i]) r.insert(a.d[i]); if(b.d[i]) r.insert(b.d[i]); } return r; } inline void lmerge(line_bsis &a,line_bsis &b) { for(register int i=60;i>=0;--i) if(b.d[i]) a.insert(b.d[i]); } void init() { p=log2(n)+1; for(int i=1;i<=n;i++) own[i].insert(w[i]); dfs(1,0); } inline void dfs(int x,int fa) { for(int i=eage.first[x];i;i=eage.nxt[i]) if(eage.t[i]!=fa) { int t=eage.t[i]; d[t]=d[x]+1; f[t][0]=x;lb[t][0]=merge(own[x],own[t]); for(int j=1;j<=p;j++) { f[t][j]=f[f[t][j-1]][j-1]; if(f[t][j]==0) break; lb[t][j]=merge(lb[t][j-1],lb[f[t][j-1]][j-1]); } dfs(t,x); } } inline int LCA(int x,int y) { clear(tmp); if(d[x]<d[y]) swap(x,y); int t=d[x]-d[y]; for(int i=p;t;i--) if(t&(1<<i)) { lmerge(tmp,lb[x][i]); x=f[x][i];t^=(1<<i); } if(x==y) return x; for(int i=p;i>=0;i--) if(f[x][i]^f[y][i]) { lmerge(tmp,lb[x][i]); lmerge(tmp,lb[y][i]); x=f[x][i];y=f[y][i]; } lmerge(tmp,lb[x][0]); lmerge(tmp,lb[y][0]); return f[x][0]; } }zt; int main() { read(n);read(q); for(int i=1;i<=n;i++) read(w[i]); for(int i=1;i<=n-1;i++) { read(x);read(y); eage.add(x,y);eage.add(y,x); } zt.init(); /*for(int i=1;i<=n;i++) for(int j=0;j<=zt.p;j++) cout<<i<<":"<<j<<" "<<zt.lb[i][j].ma()<<endl;*/ while(q--) { read(x);read(y); if(x==y) { print(zt.own[x].ma());puts(""); continue; } zt.LCA(x,y); print(zt.tmp.ma());puts(""); } return 0; }