列表

详情


NC20857. Xor Path

描述

给定一棵n个点的树,每个点有权值。定义表示  到  的最短路径上,所有点的点权异或和。
对于,求所有的异或和。

输入描述

第一行一个整数n。
接下来n-1行,每行2个整数u,v,表示u,v之间有一条边。
第n+1行有n个整数,表示每个点的权值

输出描述

输出一个整数,表示所有的异或和,其中

示例1

输入:

4
1 2
1 3
1 4
1 2 3 4

输出:

5

说明:

{\mathbb{path}(1,2)=A_1\ \mathbb{xor}\ A_2=3\\<br />\mathbb{path}(1,3)=A_1\ \mathbb{xor}\ A_3=2\\<br />\mathbb{path}(1,4)=A_1\ \mathbb{xor}\ A_4=5\\<br />\mathbb{path}(2,3)=A_2\ \mathbb{xor}\ A_1\ \mathbb{xor}\ A_3=0\\<br />\mathbb{path}(2,4)=A_2\ \mathbb{xor}\ A_1\ \mathbb{xor}\ A_4=7\\<br />\mathbb{path}(3,4)=A_3\ \mathbb{xor}\ A_1\ \mathbb{xor}\ A_4=6}
再将这6个数异或起来就可以得到答案5了。

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++14(g++5.4) 解法, 执行用时: 307ms, 内存消耗: 44220K, 提交时间: 2020-08-12 12:33:31

#include<bits/stdc++.h>
using namespace std;
#define pb push_back
const int N = 5e5+10;

int a[N],sz[N];
vector<int> g[N];
int n,ans;

void dfs(int u,int fa){
	sz[u]=1;
	int cnt=n-1;
	for(int i=0;i<g[u].size();i++){
		int v=g[u][i];
		if(v==fa) continue;
		dfs(v,u);
		cnt+=(n-sz[v])*sz[v];
		sz[u]+=sz[v];
	}
	cnt+=sz[u]*(n-sz[u]);
	cnt/=2;
	if(cnt%2) ans^=a[u];
}
int main(){
	scanf("%d",&n);
	for(int i=1;i<n;i++){
		int u,v;scanf("%d%d",&u,&v);
		g[u].pb(v);
		g[v].pb(u);
	}
	for(int i=1;i<=n;i++) scanf("%d",a+i);
	dfs(1,0);
	printf("%d",ans);
	return 0;
}

C++(clang++11) 解法, 执行用时: 289ms, 内存消耗: 42104K, 提交时间: 2020-12-25 13:09:24

#include<bits/stdc++.h>
using namespace std;
const int N=5e5+5;
#define pb push_back
int a[N],sz[N],n;
vector<int>e[N];
int ans;
void dfs(int u,int fa){
    sz[u]=1;
    int s=0;
    for(int v:e[u]){
       if(v==fa) continue;
        dfs(v,u),sz[u]+=sz[v];
        if(sz[v]&1) s++;
    }
    int t=(n-1+1LL*(sz[u]-1)*(n-sz[u])%2+s*(s-1)/2%2)%2;
    ans^=(t*a[u]);
}
int main(){
    scanf("%d",&n);for(int i=1,u,v;i<n;i++) scanf("%d%d",&u,&v),e[u].pb(v),e[v].pb(u);
    for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    dfs(1,0);
    printf("%d\n",ans);
}

上一题