列表

详情


NC15612. 树上最大值

描述

埃森哲信息技术将用您的技术改变世界。利用包括云、人工智能、智能自动化、敏捷开发和开发运维等在 内的各项最新数字方法及设计思路,重塑信息技术的明天。运用创新型解决方案,帮助客户在“以数字为先” 的当今时代保持领先地位。
 • 通过应用程序管理和服务实施来构建全新的业务模式。
 • 创建并交付定制化的解决方案,为客户解决最为复杂的技术难题。
 • 与全球领先的信息技术服务独立供应商 Microsoft, SAP, Oracle, Salesforce, Cisco, HP 及 IBM 一起,驱 动并促进业务的真正影响力。
 • 基于我们的应用性研发,让客户体验并尝试使用下一波新兴技术。 说到数字化当然少不了算法,看看下面这种题目你是否能解决 

一个连通无向图 G = (V, E),共有 n 个点,n − 1 条边,每个点有一个权值 a[i],选取集合 A 和集合 B, A ∩ B = ∅,
使得 A 中的点两两形成的路径上的点,和 B 中的点两两联通路径上的点没有任何交集。换句话说,定义 A′ ,∀u, v ∈ A,u, v 简单路径上的点 ∈ A′ , 定义 B′ ,∀u, v ∈ B,u, v 简单路径上的点 ∈ B′ , A′ ∩ B′ = ∅。
 求 A 和 B 的” 异或和”之和的最大值,“异或和”是指集合中所包含的点的权值的异或和。

输入描述

第一行为一个整数 n 第二行为 n 个整数,表示 a[1] ∼ a[n] 接下来 n − 1 行每行两个整数,代表 n − 1 条边。1 ≤ n ≤ 100000 1 ≤ a[i] ≤ 10

输出描述

一个整数,表示两个集合的“异或和”之和。

示例1

输入:

7
8 4 4 2 1 2 1
1 2
2 4
2 5
3 1
3 6
3 7

输出:

22

原站题解

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

C++14(g++5.4) 解法, 执行用时: 211ms, 内存消耗: 51220K, 提交时间: 2020-10-08 23:03:26

#include<bits/stdc++.h>
using namespace std;

#define rep(i, a, n) for(int i=(a); i<(n); ++i)
#define per(i, a, n) for(int i=(a); i>(n); --i)
#define pb emplace_back
#define mp make_pair
#define clr(a, b) memset(a, b, sizeof(a))
#define all(x) (x).begin(),(x).end()
#define lowbit(x) (x & -x)
#define fi first
#define se second
#define lson o<<1
#define rson o<<1|1
#define gmid l[o]+r[o]>>1
 
using LL = long long;
using ULL = unsigned long long;
using pii = pair<int,int>;
using PLL = pair<LL, LL>;
using UI = unsigned int;
 
const int mod = 1e9 + 7;
const int inf = 0x3f3f3f3f;
const double EPS = 1e-8;
const double PI = acos(-1.0);

const int N = 1e5 + 10;
const int M = 31;
const int L = 30;

int n;
int dfs_cnt, lft[N], rgt[N];
vector<int> V[N];
UI ans, dp[N][M], a[N], F[N][M], G[N][M], buf[M];

void join(UI *a, UI *b){
	UI x;
	per(i, L, -1){
		if(b[i] == 0)	continue;
		x = b[i];
		per(j, i, -1){
			if(!(x >> j))	continue;
			if(a[j] == 0){
				a[j] = x;
				break;
			}
			x ^= a[j];
		}
	}
}

void dfs(int x, int fa){
	lft[x] = ++dfs_cnt;

	rep(i, 0, M)	dp[x][i] = 0;
	per(i, L, -1){
		if(a[x] >> i & 1){
			dp[x][i] = a[x];
			F[dfs_cnt][i] = a[x];
			G[dfs_cnt][i] = a[x];
			break;
		}
	}

	for(int j : V[x]){
		if(j == fa)	continue;
		dfs(j, x);
		join(dp[x], dp[j]);
	}

	rgt[x] = dfs_cnt;
}

UI getval(UI *arr){
	UI ret = 0;
	per(i, L, -1){
		if((ret ^ arr[i]) > ret){
			ret ^= arr[i];
		}
	}
	return ret;
}

int main(){
	int x, y;
	scanf("%d", &n);
	rep(i, 1, n+1)	scanf("%u", a+i);
	rep(i, 1, n){
		scanf("%d %d", &x, &y);
		V[x].pb(y);
		V[y].pb(x);
	}
	dfs_cnt = 0;
	memset(F, 0, sizeof(F));
	memset(G, 0, sizeof(G));
	dfs(1, -1);
	ans = 0;
	rep(i, 1, n+1){
		join(F[i], F[i-1]);
	}
	per(i, n, 0){
		join(G[i], G[i+1]);
	}
	rep(i, 1, n+1){
		rep(j, 0, M)	buf[j] = 0;
		join(buf, F[lft[i] - 1]);
		join(buf, G[rgt[i] + 1]);
		ans = max(ans, getval(dp[i]) + getval(buf));
	}
	printf("%u\n", ans);
	return 0;
}

C++11(clang++ 3.9) 解法, 执行用时: 240ms, 内存消耗: 42344K, 提交时间: 2018-04-15 12:47:55

#include<bits/stdc++.h>
using namespace std;
#define MAXN 100005
int l[MAXN],r[MAXN],ans,N,n,m,i,j,k,h[MAXN],ne[MAXN<<1],p[MAXN<<1],a[MAXN],d[MAXN];
struct node
{
	int a[30];
	void ins(int x)
	{
		int i;
		for(i=29;~i;i--)if(x>>i&1)
      {
			if(!a[i])a[i]=x;
			x^=a[i];
			if(!x)return;
		}
	}
	int ask()
	{
		int i,j=0;
		for(i=29;~i;i--)if((j^a[i])>j)j^=a[i];
		return j;
	}
	void operator+=(const node& y)
	{
		for(int i=0;i<30;i++)ins(y.a[i]);
	}
}w1[MAXN],w2[MAXN],w[MAXN],t;
void dfs(int x)
{
	d[l[x]=++N]=x;
	w[x].ins(a[x]);
	for(int i=h[x];i;i=ne[i])if(!l[p[i]])
	{
		dfs(p[i]);
		w[x]+=w[p[i]];
	}
	r[x]=N;
}
int main()
{
	scanf("%d",&n);
	for(i=1;i<=n;i++)scanf("%d",a+i);
	for(i=1;i<n;i++)
	{
		scanf("%d%d",&j,&k);
		p[++m]=k;
		ne[m]=h[j];
		h[j]=m;
		p[++m]=j;
		ne[m]=h[k];
		h[k]=m;
	}
	dfs(1);
	for(i=1;i<=n;i++)
	{
		w1[i]=w1[i-1];
		w1[i].ins(a[d[i]]);
	}
	for(i=n;i;i--)
	{
		w2[i]=w2[i+1];
		w2[i].ins(a[d[i]]);
	}
	for(i=2;i<=n;i++)
	{
		t=w1[l[i]-1];
		t+=w2[r[i]+1];
		ans=max(ans,w[i].ask()+t.ask());
	}
	cout<<ans<<endl;
	return 0;
}

上一题