P3292 [SCOI2016]幸运数字

Captain_Paul

2018-09-03 15:25:55

Personal

题意:询问树上两点间的最大异或和 最大异或和可以用线性基解决 先树剖,用线段树维护每一条链的最大异或和就搞定了 注意pushup的不同 ``` #include<cstdio> #include<cstring> #include<cctype> #include<algorithm> #define reg register using namespace std; typedef long long ll; const int N=2e4+5; struct node { int to,nxt; }edge[N<<1]; int n,m,num,head[N],fa[N],son[N],tot[N]; int cnt,idx[N],dep[N],top[N]; ll w[N],a[N],s[N<<2][63],f[65],tmp[65]; inline ll read() { ll x=0,w=1; char c=getchar(); while (!isdigit(c)&&c!='-') c=getchar(); if (c=='-') c=getchar(),w=0; while (isdigit(c)) { x=(x<<1)+(x<<3)+c-'0'; c=getchar(); } return w?x:-x; } inline void add_edge(int from,int to) { edge[++num]=(node){to,head[from]}; head[from]=num; } void dfs(int k,int father,int deep) { int bigson=0; fa[k]=father; dep[k]=deep; tot[k]=1; for (reg int i=head[k];i;i=edge[i].nxt) { int v=edge[i].to; if (v==father) continue; dfs(v,k,deep+1); tot[k]+=tot[v]; if (bigson<tot[v]) { bigson=tot[v]; son[k]=v; } } } void dfs(int k,int tp) { idx[k]=++cnt; top[k]=tp; a[cnt]=w[k]; if (!son[k]) return; dfs(son[k],tp); for (reg int i=head[k];i;i=edge[i].nxt) { int v=edge[i].to; if (!idx[v]) dfs(v,v); } } inline void insert(ll *a,ll x) { for (reg int i=60;~i;i--) if (x&(1ll<<i)) if (!a[i]) {a[i]=x; break;} else x^=a[i]; } inline void merge(ll *a,ll *b) { for (reg int i=60;~i;i--) if (b[i]) insert(a,b[i]); } inline ll query() { ll ans=0; for (reg int i=60;~i;i--) if (ans<(ans^f[i])) ans^=f[i]; return ans; } void build(int l,int r,int now) { if (l==r) { insert(s[now],a[l]); return; } int mid=(l+r)>>1; build(l,mid,now<<1); build(mid+1,r,now<<1|1); merge(s[now],s[now<<1]); merge(s[now],s[now<<1|1]); } void Query(int L,int R,int l,int r,int now) { if (l>R||r<L) return; if (l>=L&&r<=R) {merge(tmp,s[now]); return;} int mid=(l+r)>>1; if (mid>=R) Query(L,R,l,mid,now<<1); else if (mid<L) Query(L,R,mid+1,r,now<<1|1); else { Query(L,mid,l,mid,now<<1); Query(mid+1,R,mid+1,r,now<<1|1); } } inline ll getans(int x,int y) { memset(f,0,sizeof(f)); while (top[x]!=top[y]) { if (dep[top[x]]<dep[top[y]]) swap(x,y); memset(tmp,0,sizeof(tmp)); Query(idx[top[x]],idx[x],1,n,1); merge(f,tmp); x=fa[top[x]]; } if (dep[x]>dep[y]) swap(x,y); memset(tmp,0,sizeof(tmp)); Query(idx[x],idx[y],1,n,1); merge(f,tmp); return query(); } int main() { n=read(),m=read(); for (reg int i=1;i<=n;w[i++]=read()); for (reg int i=1;i<n;i++) { int x=read(),y=read(); add_edge(x,y); add_edge(y,x); } dfs(1,0,1); dfs(1,1); build(1,n,1); while (m--) { int x=read(),y=read(); printf("%lld\n",getans(x,y)); } return 0; } ```