本文主要是介绍【SCOI2016】bzoj4568 幸运数字,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
Description A 国共有 n 座城市,这些城市由 n-1 条道路相连,使得任意两座城市可以互达,且路径唯一。每座城市都有一个
幸运数字,以纪念碑的形式矗立在这座城市的正中心,作为城市的象征。一些旅行者希望游览 A 国。旅行者计划 乘飞机降落在 x 号城市,沿着 x
号城市到 y 号城市之间那条唯一的路径游览,最终从 y 城市起飞离开 A 国。
在经过每一座城市时,游览者就会有机会与这座城市的幸运数字拍照,从而将这份幸运保存到自己身上。然而,幸
运是不能简单叠加的,这一点游览者也十分清楚。他们迷信着幸运数字是以异或的方式保留在自己身上的。例如, 游览者拍了 3 张照片,幸运值分别是
5,7,11,那么最终保留在自己身上的幸运值就是 9(5 xor 7 xor 11)。
有些聪明的游览者发现,只要选择性地进行拍照,便能获得更大的幸运值。例如在上述三个幸运值中,只选择 5 和 11 ,可以保留的幸运值为 14
。现在,一些游览者找到了聪明的你,希望你帮他们计算出在他们的行程安排中 可以保留的最大幸运值是多少。Input 第一行包含 2 个正整数 n ,q,分别表示城市的数量和旅行者数量。第二行包含 n 个非负整数,其中第 i 个整 数 Gi 表示
i 号城市的幸运值。随后 n-1 行,每行包含两个正整数 x ,y,表示 x 号城市和 y 号城市之间有一 条道路相连。随后 q
行,每行包含两个正整数 x ,y,表示这名旅行者的旅行计划是从 x 号城市到 y 号城市。N
<=20000,Q<=200000,Gi<=2^60Output 输出需要包含 q 行,每行包含 1 个非负整数,表示这名旅行者可以保留的最大幸运值。
倍增lca,暴力合并线性基。
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define LL long long
const int maxd=16,maxp=60;
LL rdLL()
{LL x=0;char c=getchar();while (c<'0'||c>'9') c=getchar();while (c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}return x;
}
int rd()
{int x=0;char c=getchar();while (c<'0'||c>'9') c=getchar();while (c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}return x;
}
struct mat
{LL a[65];LL val(){LL ret=0;for (int i=maxp;i>=0;i--) ret=max(ret,ret^a[i]);return ret;}void clear(){memset(a,0,sizeof(a));}void add(LL x){if (!x) return;for (int i=maxp;i>=0;i--)if ((x>>i)&1){if (!a[i]){a[i]=x;return;}else x^=a[i];}}void add(mat mt){for (int i=maxp;i>=0;i--) add(mt.a[i]);}
}f[20010][17],now;
int n,q,fir[20010],ne[40010],to[40010],fa[20010][17],dep[20010];
LL val[20010];
void add(int num,int u,int v)
{ne[num]=fir[u];fir[u]=num;to[num]=v;
}
void dfs(int u)
{int i,v;for (i=fir[u];i;i=ne[i])if ((v=to[i])!=fa[u][0]){fa[v][0]=u;dep[v]=dep[u]+1;dfs(v);}
}
int main()
{int i,k,u,v;n=rd();q=rd();for (i=1;i<=n;i++) val[i]=rdLL();for (i=1;i<n;i++){u=rd();v=rd();add(i*2,u,v);add(i*2+1,v,u);}dep[1]=1;dfs(1);for (i=1;i<=n;i++) f[i][0].add(val[i]);for (k=1;k<=maxd;k++)for (i=1;i<=n;i++){fa[i][k]=fa[fa[i][k-1]][k-1];f[i][k]=f[i][k-1];if (fa[i][k-1]) f[i][k].add(f[fa[i][k-1]][k-1]);}while (q--){u=rd();v=rd();now.clear();if (dep[u]<dep[v]) swap(u,v);for (k=maxd;k>=0;k--)if (dep[u]-(1<<k)>=dep[v]){now.add(f[u][k]);u=fa[u][k];}if (u==v){now.add(val[u]);printf("%lld\n",now.val());continue;}for (k=maxd;k>=0;k--)if (fa[u][k]!=fa[v][k]){now.add(f[u][k]);now.add(f[v][k]);u=fa[u][k];v=fa[v][k];}now.add(val[u]);now.add(val[v]);now.add(val[fa[u][0]]);printf("%lld\n",now.val());}
}
这篇关于【SCOI2016】bzoj4568 幸运数字的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!