当前位置: 代码迷 >> 综合 >> 4568: [Scoi2016]幸运数字
  详细解决方案

4568: [Scoi2016]幸运数字

热度:60   发布时间:2023-10-29 13:54:20.0

又是一道线性基的题目。。

我们只需要对这棵树维护一个倍增的线性基就可以了,方法类似于LCA的求法

至于怎么合并两个线性基,我们只需要将两个基的全部数字拿出来,然后在重新插进去一个新的基就可以了

注意细节。。

我一开始因为数组开小了还WA了一发。。

code:

#include<cstdio>
#include<cstring>
#define swap(x,y) {LL tt=x;x=y;y=tt;}
typedef long long LL;
const LL N=20005;
LL n,q;
LL a[N];
struct qq
{LL x,y,last;
}e[N*2];LL num,last[N];
void init (LL x,LL y)
{num++;e[num].x=x;e[num].y=y;e[num].last=last[x];last[x]=num;
}
LL fa[N][21],lalal[N][21][65],dep[N];//祖先  线性基   深度 
void ins (LL x,LL y,LL xx)
{for (LL u=62;u>=0;u--)if (xx>>u&1){if (lalal[x][y][u]==0) {lalal[x][y][u]=xx;return ;}	xx=xx^lalal[x][y][u];}
}
void Merge (LL x,LL y,LL x1,LL y1)//我现在要更新x  y这个地方      用的是将x1y1吃掉 
{for (LL u=62;u>=0;u--)if (lalal[x1][y1][u]!=0) ins(x,y,lalal[x1][y1][u]);
}
void dfs (LL x,LL Fa)
{dep[x]=dep[Fa]+1;fa[x][0]=Fa;for (LL u=1;(1<<u)<=dep[x];u++) fa[x][u]=fa[fa[x][u-1]][u-1];/*=================================*/ins(x,0,a[x]);ins(x,0,a[Fa]);for (LL u=1;(1<<u)<=dep[x];u++) Merge(x,u,x,u-1),Merge(x,u,fa[x][u-1],u-1);/*=================================*/for (LL u=last[x];u!=-1;u=e[u].last){LL y=e[u].y;if (y==Fa) continue;dfs(y,x);}
}
LL Ans;
void solve (LL x,LL y)
{for (LL u=0;u<65;u++) lalal[Ans][0][u]=0;if (dep[x]<dep[y]) swap(x,y);for (LL u=20;u>=0;u--)if (dep[fa[x][u]]>=dep[y]){Merge(Ans,0,x,u);x=fa[x][u];}//printf("YES:%lld %lld\n",x,y);if (x!=y){for (LL u=20;u>=0;u--)if (fa[x][u]!=fa[y][u]){//	printf("YES:%lld %lld %lld %lld %lld\n",x,y,fa[x][u],fa[y][u],u);Merge(Ans,0,x,u);Merge(Ans,0,y,u);x=fa[x][u];y=fa[y][u];//printf("YES:%lld %lld\n",x,y);}Merge(Ans,0,x,0);Merge(Ans,0,y,0);x=fa[x][0];}ins(Ans,0,a[x]);LL ans=0;for (LL u=62;u>=0;u--)if ((ans^lalal[Ans][0][u])>ans) ans^=lalal[Ans][0][u];printf("%lld\n",ans);
}
int main()
{memset(lalal,0,sizeof(lalal));num=0;memset(last,-1,sizeof(last));scanf("%lld%lld",&n,&q);Ans=n+1;for (LL u=1;u<=n;u++)	scanf("%lld",&a[u]);for (LL u=1;u<n;u++){LL x,y;scanf("%lld%lld",&x,&y);init(x,y);init(y,x);}dep[0]=0;dfs(1,0);/*printf("lalal:");printf("%lld %lld\n",fa[2][0],fa[2][1]);printf("%lld %lld\n",fa[3][0],fa[3][1]);*/for (LL u=1;u<=q;u++){LL x,y;scanf("%lld%lld",&x,&y);solve(x,y);}return 0;
}