2017 ACM-ICPC 亚洲区(西安赛区)网络赛 G. Xor

Posted mxzf0213

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2017 ACM-ICPC 亚洲区(西安赛区)网络赛 G. Xor相关的知识,希望对你有一定的参考价值。

There is a tree with nn nodes. For each node, there is an integer value a_ia?i??, (1 \le a_i \le 1,000,000,0001a?i??1,000,000,000 for 1 \le i \le n1in). There is qq queries which are described as follow: Assume the value on the path from node aa to node bb is t_0, t_1, \cdots t_mt?0??,t?1??,?t?m??. You are supposed to calculate t_0t?0?? xor t_kt?k?? xor t_{2k}t?2k?? xor ... xor t_{pk}t?pk?? (pk \le m)(pkm).

Input Format

There are multi datasets. (\sum n \le 50,000, \sum q \le 500,000)(n50,000,q500,000).

For each dataset: In the first n-1n1 lines, there are two integers u,vu,v, indicates there is an edge connect node uu and node vv.

In the next nn lines, There is an integer a_ia?i?? (1 \le a_i \le 1,000,000,0001a?i??1,000,000,000).

In the next qq lines, There is three integers a,ba,band kk. (1 \le a,b,k \le n1a,b,kn).

Output Format

For each query, output an integer in one line, without any additional space.

样例输入

5 6
1 5
4 1
2 1
3 2
19
26
0
8
17
5 5 1
1 3 2
3 2 1
5 4 2
3 4 4
1 4 5

样例输出

17
19
26
25
0
19
分析:求树上路径从距离起点为k的倍数的权值和;
   大于根号n暴力,小于的话预处理,处理到根的前缀异或和;

代码:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <climits>
#include <cstring>
#include <string>
#include <set>
#include <bitset>
#include <map>
#include <queue>
#include <stack>
#include <vector>
#include <cassert>
#include <ctime>
#define rep(i,m,n) for(i=m;i<=(int)n;i++)
#define inf 0x3f3f3f3f
#define mod 1000000007
#define vi vector<int>
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define ll long long
#define pi acos(-1.0)
#define pii pair<int,int>
#define sys system("pause")
#define ls (rt<<1)
#define rs (rt<<1|1)
#define all(x) x.begin(),x.end()
const int maxn=5e4+10;
const int N=2e5+10;
using namespace std;
ll gcd(ll p,ll q){return q==0?p:gcd(q,p%q);}
ll qmul(ll p,ll q,ll mo){ll f=0;while(q){if(q&1)f=(f+p)%mo;p=(p+p)%mo;q>>=1;}return f;}
ll qpow(ll p,ll q,ll mo){ll f=1;while(q){if(q&1)f=f*p%mo;p=p*p%mo;q>>=1;}return f;}
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;
}
/*
6 1
3 2
1 4
4 6
6 2
1 5
60
2
75
34
60
15
4 6 1
ans:45
*/

以上是关于2017 ACM-ICPC 亚洲区(西安赛区)网络赛 G. Xor的主要内容,如果未能解决你的问题,请参考以下文章

2017 ACM-ICPC 亚洲区(西安赛区)网络赛: B. Coin 概率题

2017 ACM-ICPC 亚洲区(西安赛区)网络赛 G. Xor

2017 ACM-ICPC 亚洲区(西安赛区)网络赛 B.Coin(基本概率+二项式展开)

2017 ACM-ICPC 亚洲区(西安赛区)网络赛 F.Trig Function(论文+组合数)

2017 ACM-ICPC 亚洲区(西安赛区)网络赛 B题 Coin 题解

017 ACM-ICPC 亚洲区(西安赛区)网络赛 Coin 概率+矩阵快速幂