P3292 [SCOI2016] 幸运数字
[SCOI2016] 幸运数字
题目描述
A 国共有
一些旅行者希望游览 A 国。旅行者计划乘飞机降落在
例如,游览者拍了
有些聪明的游览者发现,只要选择性地进行拍照,便能获得更大的幸运值。例如在上述三个幸运值中,只选择
提示
对于
Solution:
我们知道线性基是可以合并的,我们先对于每个点记录该点到根这条路径上所有点构成的线性基,但在插入时,对于相同的位,我们优先取更深的那个点,那么我们在从这个树上取出一条路径上的线性基时,直接判断这个点的深度是否大于 lca 然后我们就能取出这条路径上的线性基,直接最大化答案就好了。
Code:
#include<bits/stdc++.h> #define int long long using namespace std; const int N=2e5+5; const int inf=65; const int lg=15; int n,m,e_cnt; int head[N],a[N],dep[N],base[inf]; int d[N][inf],pos[N][inf],fa[N][inf]; struct Edge{ int to,nxt; }e[N<<1]; void add(int x,int y) { e[++e_cnt]={y,head[x]}; head[x]=e_cnt; } void ins(int x,int d[],int pos[]) { int v=a[x]; for(int i=60;i>=0;i--) { if(v&(1ll<<i)) { if(!d[i]) { d[i]=v; pos[i]=x; break; } if(dep[x]>dep[pos[i]]) { swap(x,pos[i]);swap(d[i],v); } v^=d[i]; } } } void dfs(int x) { dep[x]=dep[fa[x][0]]+1; for(int i=1;i<=lg;i++) { fa[x][i]=fa[fa[x][i-1]][i-1]; } for(int i=0;i<=60;i++) { pos[x][i]=pos[fa[x][0]][i]; d[x][i]=d[fa[x][0]][i]; } ins(x,d[x],pos[x]); for(int i=head[x];i;i=e[i].nxt) { int to=e[i].to; if(to==fa[x][0])continue; fa[to][0]=x; dfs(to); } } int LCA(int x,int y) { if(dep[x]<dep[y])swap(x,y); for(int i=lg;i>=0;i--) { if(dep[fa[x][i]]>=dep[y])x=fa[x][i]; } if(x==y)return x; for(int i=lg;i>=0;i--) { if(fa[x][i]!=fa[y][i]) { x=fa[x][i];y=fa[y][i]; } } return fa[x][0]; } int ANS(int x,int y,int lca) { for(int i=60;i>=0;i--) { if(dep[pos[x][i]]>=dep[lca]) { base[i]=d[x][i]; } else base[i]=0; } for(int i=60;i>=0;i--) { if(dep[pos[y][i]]>=dep[lca]) { int p=d[y][i]; if(!p)continue; for(int j=i;j>=0;j--) { if(p&(1ll<<j)) { if(!base[j]) { base[j]=p; break; } p^=base[j]; } } } } int ans=0; for(int i=60;i>=0;i--) { ans= (ans^base[i])>ans ? ans^base[i] : ans; } return ans; } void work() { cin>>n; cin>>m; for(int i=1;i<=n;i++) { scanf("%lld",&a[i]); } for(int i=1,x,y;i<n;i++) { scanf("%lld%lld",&x,&y); add(x,y);add(y,x); } dfs(1); for(int i=1,x,y;i<=m;i++) { scanf("%lld%lld",&x,&y); int lca=LCA(x,y); int ans=ANS(x,y,lca); printf("%lld\n",ans); } } #undef int int main() { //freopen("P3292_1.in","r",stdin);freopen("P3292.out","w",stdout); work(); }