BZOJ 4568 幸运数字 发表于 2017-03-27 | 更新于 2018-06-18 Link线性基学得和没学差不多。。 Solution倍增维护线性基,需要特判起点和终点相等的情况。。 Code123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128#include "lucida"using std::fill;using std::swap;typedef unsigned long long qword;const int MAXN=20000+11,MAXLOG=16;int log_2[MAXN];struct _{_(){ log_2[0]=-1; for(int lg=1;lg<MAXN;++lg) { log_2[lg]=log_2[lg>>1]+1; }}}Auto;struct Edge { int to;Edge *pre; Edge(int to,Edge *pre):to(to),pre(pre) {} void *operator new(size_t) { static Edge *Me=alloc(Edge,MAXN<<1); return Me++; }}*G[MAXN];void Adde(int f,int t) { G[f]=new Edge(t,G[f]); G[t]=new Edge(f,G[t]);}struct Basis { qword a[62]; Basis() { fill(a,a+62,0); } qword &operator [](const int &x) { return a[x]; } const qword &operator [](const int &x) const { return a[x]; } void Insert(qword x) { for(int lg=61;~lg;--lg) { if(x>>lg&1) { if(a[lg]) { x^=a[lg]; } else { a[lg]=x; break; } } } } friend Basis Merge(Basis a,const Basis &b) { for(int lg=61;~lg;--lg) { if(b[lg]) {//超强的优化! a.Insert(b[lg]); } } return a; } qword Max() { qword res=0; for(int lg=61;~lg;--lg) { chkmx(res,res^a[lg]); } return res; }};qword a[MAXN];int par[MAXN][MAXLOG],dep[MAXN],fa[MAXN];Basis basis[MAXN][MAXLOG];void DFS(int pos) { dep[pos]=dep[fa[pos]]+1; par[pos][0]=fa[pos]; basis[pos][0].Insert(a[pos]); basis[pos][0].Insert(a[fa[pos]]); for(int lg=1;lg<=log_2[dep[pos]];++lg) { basis[pos][lg]=Merge(basis[pos][lg-1],basis[par[pos][lg-1]][lg-1]); par[pos][lg]=par[par[pos][lg-1]][lg-1]; } for(Edge *e=G[pos];e;e=e->pre) { if(e->to!=fa[pos]) { int u=e->to; fa[u]=pos; DFS(u); } }}qword Query(int p1,int p2) { if(p1==p2) { return a[p1]; } else { Basis b; if(dep[p1]<dep[p2]) { swap(p1,p2); } for(int len=dep[p1]-dep[p2],lg=log_2[len];~lg;--lg) { if(len>>lg&1) { b=Merge(b,basis[p1][lg]); p1=par[p1][lg]; } } if(p1!=p2) { for(int lg=log_2[dep[p1]];~lg;--lg) { if(par[p1][lg]!=par[p2][lg]) { b=Merge(b,Merge(basis[p1][lg],basis[p2][lg])); p1=par[p1][lg];p2=par[p2][lg]; } } b=Merge(b,Merge(basis[p1][0],basis[p2][0])); } return b.Max(); }}int main() { freopen("input","r",stdin); freopen("output","w",stdout); int n,Q;is>>n>>Q; for(int i=1;i<=n;++i) { is>>a[i]; } for(int i=1;i<=n-1;++i) { int x,y;is>>x>>y; Adde(x,y); } DFS(1); for(int i=1;i<=Q;++i) { int x,y;is>>x>>y; qword Ans=Query(x,y); os<<Ans<<'\n'; } return 0;}