Xor 分段处理+LCA.

来源:互联网 发布:橙e付网络 编辑:程序博客网 时间:2024/06/06 19:05
题意;n个结点的树,点带权,q次询问,问从a到b路径为t0,t1...tm,问路径上每k个点异或一次的值为多少? n<=1e4,q<=5e5.

k>sqrt(n)时 显然可以暴力往lca上跳,因为是从x->y,y往上跳时,第一次要跳dis%k.

k<sqrt(n)时 预处理出dp[u][k] u每隔k个到rt的异或值.细节看代码..

#include <bits/stdc++.h> #define rep(i,m,n) for(i=m;i<=(int)n;i++)#define inf 0x3f3f3f3fconst int maxn=5e4+10;const int N=2e5+10;using namespace std;int n,m,k,t,dp[maxn][310],fa[20][maxn],dep[maxn],a[maxn],sz,q,head[maxn],tot;struct node{    int to,nxt;}e[maxn<<1];void add(int x,int y){    e[tot].to=y;    e[tot].nxt=head[x];    head[x]=tot++;}int lca(int x,int y){    int i;    if(dep[x]<dep[y])swap(x,y);    for(i=19;i>=0;i--)if(dep[fa[i][x]]>=dep[y])x=fa[i][x];    if(x==y)return x;    for(i=19;i>=0;i--)    {        if(fa[i][x]!=fa[i][y])        {            x=fa[i][x],            y=fa[i][y];        }    }    return fa[0][x];}int find(int x,int y){    int i;    for(i=19;i>=0;i--)    {        if(y>>i&1)        {            x=fa[i][x];            if(x==0)return 0;        }    }    return x;}void dfs(int x,int y){    int i;    dep[x]=dep[y]+1;    for(i=1;fa[i-1][fa[i-1][x]];i++)        fa[i][x]=fa[i-1][fa[i-1][x]];    rep(i,1,sz)    {        dp[x][i]=a[x];        dp[x][i]^=dp[find(x,i)][i];    }    for(i=head[x];i!=-1;i=e[i].nxt)    {        int z=e[i].to;        if(z==y)continue;        fa[0][z]=x;        dfs(z,x);    }}int main(){    int i,j;    while(~scanf("%d%d",&n,&q))    {        sz=round(sqrt(n));        rep(i,1,n)        {            head[i]=-1;            rep(j,0,19)fa[j][i]=0;        }        tot=0;        rep(i,1,n-1)        {            int x,y;            scanf("%d%d",&x,&y);            add(x,y);add(y,x);        }        rep(i,1,n)scanf("%d",&a[i]);        dfs(1,0);        while(q--)        {            int x,y,k;            int ret=0;            scanf("%d%d%d",&x,&y,&k);            if(x==y)            {                printf("%d\n",a[x]);                continue;            }            int fa=lca(x,y),len=dep[x]+dep[y]-2*dep[fa],pos;            if((dep[x]-dep[fa])%k==0&&fa!=x&&fa!=y)ret^=a[fa];            if(k>sz)            {                if(fa!=x)                {                    pos=x;                    ret^=a[pos];                    while(dep[j=find(pos,k)]>=dep[fa])                    {                        pos=j;                        ret^=a[pos];                    }                }                if(fa!=y)                {                    pos=find(y,len%k);                    if(dep[pos]>=dep[fa])                    {                        ret^=a[pos];                        while(dep[j=find(pos,k)]>=dep[fa])                        {                            pos=j;                            ret^=a[pos];                        }                    }                }            }            else            {                int len1=dep[x]-dep[fa];                if(fa!=x)                {                    len1=len1/k*k;                    pos=find(x,len1);                    ret=(ret^dp[x][k]^dp[pos][k]^a[pos]);                }                if(fa!=y)                {                    int st=find(y,len%k);                    if(dep[st]>=dep[fa])                    {                        len1=dep[st]-dep[fa];                        len1=len1/k*k;                        pos=find(st,len1);                        ret=(ret^dp[st][k]^dp[pos][k]^a[pos]);                    }                }            }            printf("%d\n",ret);        }    }    return 0;}