CodeForces-1485E-Move and Swap

题目大意

CodeForces-1485E-Move and Swap

n个节点的树,每个节点(2~n)有值a[i],一开始红色点和蓝色点都在头节点1,移动d步求最大的|a[i]-a[j]|之和。

每一步:
红色点只能移动到r的子节点
蓝色点可以移动到下一层的任意一点
每次可以选择交换红色点和蓝色点的位置(也可以不交换)

思路

一开始想着贪心:每次选择每层最大的和最小的,但是这样贪心显然不对,样例都过不了。

于是想树形DP:

假设红色点和蓝色点不可以交换,dp[i]表示红色点当前走到i点时最大的总和,fa[i]表示节点i的父亲节点。那么dp[i]=max(dp[i],dp[fa[i]]+|a[i]-a[j]|)(j就是蓝色点,即与i同层的节点),这里可以依靠预处理出同一层最大的a[i]的值和最小的a[i]的值。如果红色点和蓝色点可以交换,那么dp[i]=max(dp[i],dp[fa[j]]+abs(a[i]-a[j])),即dp[i]=max(dp[i],dp[fa[j]]+a[j]-a[i],dp[fa[j]]-a[j]+a[i]),这里可以预处理出dp[fa[j]]+a[j]和dp[fa[j]]-a[j].

首先用dfs求出深度,将同一深度的放到一个集合,然后通过对每一个深度进行预处理求处最小的a[i]和最大的a[i]以及最大的dp[fa[i]]+a[i]和dp[fa[i]]-a[i].

代码

#include<bits/stdc++.h>
using namespace std;
const int maxn=4e5+50;
typedef long long ll;
int T,n,k=1,head[maxn];ll a[maxn],dp[maxn];
struct Edge{
	int to,next;
}edge[maxn*2];
void add(int u,int v){
	edge[++k].to=v;edge[k].next=head[u];head[u]=k;
} 
int deep[maxn],fa[maxn],Maxx_deep;vector<int>s[maxn];
void dfs(int u,int f){
	deep[u]=deep[f]+1;fa[u]=f;s[deep[u]].push_back(u);
	Maxx_deep=max(Maxx_deep,deep[u]);
	for(int i=head[u];i;i=edge[i].next){
		if(edge[i].to==f)continue;
		dfs(edge[i].to,u);
	}
}
int main(){
	cin>>T;
	while(T--){
		k=1;Maxx_deep=0;
		cin>>n;
		memset(head,0,sizeof(int)*(2*n+10));
		memset(dp,0,sizeof(ll)*(n+5));
		for(int i=2;i<=n;i++){
			int f;cin>>f;
			add(f,i);add(i,f);
		}
		for(int i=2;i<=n;i++)cin>>a[i];
		dfs(1,1);
		ll ans=-1e18;
		for(int i=2;i<=Maxx_deep;i++){
			ll minn=1e18,maxx=-1e18,maxxe1=-1e18,maxxe2=-1e18;
			for(int j=0;j<s[i].size();j++){
				minn=min(minn,a[s[i][j]]);
				maxx=max(maxx,a[s[i][j]]);
				maxxe1=max(maxxe1,dp[fa[s[i][j]]]+a[s[i][j]]);
				maxxe2=max(maxxe2,dp[fa[s[i][j]]]-a[s[i][j]]);
			}
			for(int j=0;j<s[i].size();j++){
				dp[s[i][j]]=max(dp[s[i][j]],dp[fa[s[i][j]]]+max(abs(a[s[i][j]]-minn),abs(a[s[i][j]]-maxx)));
				dp[s[i][j]]=max(dp[s[i][j]],maxxe1-a[s[i][j]]);
				dp[s[i][j]]=max(dp[s[i][j]],maxxe2+a[s[i][j]]);
				ans=max(ans,dp[s[i][j]]);
			}
		}
		cout<<ans<<endl;
		for(int i=1;i<=Maxx_deep;i++)s[i].clear();
	}
	return 0;
}
上一篇:JetBrains macOS下快捷键 & 设置-不断完善……


下一篇:Unity和C#-游戏开发-贪吃蛇+源代码工程