BZOJ 4568: [Scoi2016]幸运数字
2016-11-04 19:33
405 查看
题意:
A 国共有 n 座城市,这些城市由 n-1 条道路相连,使得任意两座城市可以互达,且路径唯一。每座城市都有一个
幸运数字,以纪念碑的形式矗立在这座城市的正中心,作为城市的象征。一些旅行者希望游览 A 国。旅行者计划
乘飞机降落在 x 号城市,沿着 x 号城市到 y 号城市之间那条唯一的路径游览,最终从 y 城市起飞离开 A 国。
在经过每一座城市时,游览者就会有机会与这座城市的幸运数字拍照,从而将这份幸运保存到自己身上。然而,幸
运是不能简单叠加的,这一点游览者也十分清楚。他们迷信着幸运数字是以异或的方式保留在自己身上的。例如,
游览者拍了 3 张照片,幸运值分别是 5,7,11,那么最终保留在自己身上的幸运值就是 9(5 xor 7 xor 11)。
有些聪明的游览者发现,只要选择性地进行拍照,便能获得更大的幸运值。例如在上述三个幸运值中,只选择 5
和 11 ,可以保留的幸运值为 14 。现在,一些游览者找到了聪明的你,希望你帮他们计算出在他们的行程安排中
可以保留的最大幸运值是多少。
思路:
点分治+线性基
关于线性基http://www.cnblogs.com/ljh2000-jump/p/5869991.html
就是考虑对每个点保存到重心的线性基
如果答案的两个端点不在同一个子树里就暴力合并线性基,然后得到答案
如果在同一个子树里的话,我们就把这个询问传给那个子树,然后利用子树的重心来得到答案
用的Claris的点分治模板
A 国共有 n 座城市,这些城市由 n-1 条道路相连,使得任意两座城市可以互达,且路径唯一。每座城市都有一个
幸运数字,以纪念碑的形式矗立在这座城市的正中心,作为城市的象征。一些旅行者希望游览 A 国。旅行者计划
乘飞机降落在 x 号城市,沿着 x 号城市到 y 号城市之间那条唯一的路径游览,最终从 y 城市起飞离开 A 国。
在经过每一座城市时,游览者就会有机会与这座城市的幸运数字拍照,从而将这份幸运保存到自己身上。然而,幸
运是不能简单叠加的,这一点游览者也十分清楚。他们迷信着幸运数字是以异或的方式保留在自己身上的。例如,
游览者拍了 3 张照片,幸运值分别是 5,7,11,那么最终保留在自己身上的幸运值就是 9(5 xor 7 xor 11)。
有些聪明的游览者发现,只要选择性地进行拍照,便能获得更大的幸运值。例如在上述三个幸运值中,只选择 5
和 11 ,可以保留的幸运值为 14 。现在,一些游览者找到了聪明的你,希望你帮他们计算出在他们的行程安排中
可以保留的最大幸运值是多少。
思路:
点分治+线性基
关于线性基http://www.cnblogs.com/ljh2000-jump/p/5869991.html
就是考虑对每个点保存到重心的线性基
如果答案的两个端点不在同一个子树里就暴力合并线性基,然后得到答案
如果在同一个子树里的话,我们就把这个询问传给那个子树,然后利用子树的重心来得到答案
用的Claris的点分治模板
#include<stdio.h> #include<string.h> typedef long long LL; const int maxn = 20005; const int maxm = 200005; struct node { int x,y; }q[maxm]; LL Pow[65]; struct B { LL p[60]; B() { memset(p,0,sizeof(p)); } inline void Insert(LL x) { for(int i=59;i>=0;--i){ if(!(x&Pow[i])) continue; if(!p[i]){ p[i]=x;break; } x^=p[i]; } } inline LL Ask() { LL Ans=0; for(int i=59;i>=0;--i) if((Ans^p[i])>Ans) Ans^=p[i]; return Ans; } }h[maxn],b; struct Node { int next,to; }e[maxn*2],Qes[maxm*2]; int h1[maxn],h2[maxm],tot1,tot2; inline void add(int a,int b) { e[++tot1].next=h1[a]; e[tot1].to=b; h1[a]=tot1; } inline void ADD(int a,int b) { Qes[++tot2].next=h2[a]; Qes[tot2].to=b; h2[a]=tot2; } int n,m; int pos[maxn]; LL A[maxn],ans[maxm]; int Son[maxn],Maxv[maxn],vis[maxn]; int root,Sum; inline void Getroot(int u,int fa) { Son[u]=1;Maxv[u]=0; for(int i=h1[u];~i;i=e[i].next) { int v=e[i].to; if(v==fa|vis[v]) continue; Getroot(v,u); Son[u]+=Son[v]; if(Son[v]>Maxv[u]) Maxv[u]=Son[v]; } if(Sum-Son[u]>Maxv[u]) Maxv[u]=Sum-Son[u]; if(Maxv[u]<Maxv[root]) root=u; } inline void GetG(int u,int fa,int tp) { pos[u]=tp; h[u]=h[fa]; h[u].Insert(A[u]); for(int i=h1[u];~i;i=e[i].next) { int v=e[i].to; if(v==fa||vis[v]) continue; GetG(v,u,tp); } } int qes[maxm],qes_num; //第一次调用时需令Son[1]=n; inline void Solve(int u) { if(h2[u]==-1) return ; Sum=Maxv[0]=Son[u]; Getroot(u,root=0); int rt=root; pos[root]=root; vis[rt]=true; h[rt]=B();h[rt].Insert(A[rt]); for(int i=h1[rt];~i;i=e[i].next) { int v=e[i].to; if(vis[v]) continue; GetG(v,rt,v); } qes_num=0; for(int i=h2[u];~i;i=Qes[i].next) qes[qes_num++]=Qes[i].to; h2[u]=-1; for(int i=0;i<qes_num;++i) { int v=qes[i]; // printf("%d: %d(%d) %d(%d)\n",v,q[v].x,pos[q[v].x],q[v].y,pos[q[v].y]); if(pos[q[v].x]==pos[q[v].y]) { ADD(pos[q[v].x],v); continue; } b=h[q[v].x]; for(int j=0;j<60;++j) if(h[q[v].y].p[j]) { b.Insert(h[q[v].y].p[j]); } ans[v]=b.Ask(); } for(int i=h1[rt];~i;i=e[i].next) { int v=e[i].to; if(vis[v]) continue; Solve(v); } } int main() { memset(h1,-1,sizeof(h1)); memset(h2,-1,sizeof(h2)); tot1=tot2=-1; Pow[0]=1; for(int i=1;i<=60;++i) Pow[i]=Pow[i-1]<<1; scanf("%d%d",&n,&m); for(int i=1;i<=n;++i) scanf("%lld",&A[i]); for(int i=1;i<n;++i) { int u,v; scanf("%d%d",&u,&v); add(u,v);add(v,u); } for(int i=1;i<=m;++i) { scanf("%d%d",&q[i].x,&q[i].y); if(q[i].x==q[i].y) ans[i]=A[q[i].x]; else ADD(1,i); } Son[1]=n; memset(vis,0,sizeof(vis)); Solve(1); for(int i=1;i<=m;++i) printf("%lld\n",ans[i]); return 0; }
相关文章推荐
- bzoj 4568: [Scoi2016]幸运数字(树上倍增+线性基)
- 【BZOJ 4568】【SCOI 2016】幸运数字
- BZOJ 4568: [Scoi2016]幸运数字
- BZOJ 4568 [Scoi2016]幸运数字
- BZOJ4568 [Scoi2016]幸运数字
- BZOJ4568: [Scoi2016]幸运数字【线性基】
- bzoj 4568 [Scoi2016]幸运数字 倍增+线性基
- bzoj 4568: [Scoi2016]幸运数字
- bzoj 4568: [Scoi2016]幸运数字【树链剖分+线段树+线性基】
- 【BZOJ 4568】[Scoi2016]幸运数字
- bzoj 4568 [SCOI 2016] 幸运数字
- BZOJ 4568: [Scoi2016]幸运数字 [线性基 倍增]
- BZOJ 4568 [Scoi2016]幸运数字 【倍增线性基
- [BZOJ]4568: [Scoi2016]幸运数字 倍增+线性基
- BZOJ 4568 [Scoi2016]幸运数字 ——线性基 倍增
- [线性基 树链剖分 线段树 || ST表 || 点分治] BZOJ 4568 [Scoi2016]幸运数字
- bzoj 4568: [Scoi2016]幸运数字 倍增维护线性基
- 【BZOJ 4568】 4568: [Scoi2016]幸运数字 (线性基+树链剖分+线段树)
- BZOJ 4568: [Scoi2016]幸运数字
- bzoj 4568: [Scoi2016]幸运数字 (高斯消元求解线性基)