CF1485E Move and Swap
很好的题呢
n个节点的树,根为1,所有叶子的深度都是D,一开始根节点上有两个颜色分别微R,B的球,你执行下列操作D-1次:
1.R点跳到子树内
2.B点跳到下一层的任意节点
3.交换(R,B)[选做]
每次操作结束时,加上上abs(a[R所在点]-a[B所在点])
- 思路:这样每层都是一个子问题,而且每次抉择都会影响下一个子问题,所以这个没办法贪心,于是考虑树上dp。
dp[i]:表示R在i结点,第dep[i]~D层总最大价值和
不交换:\(dp[u]=max(dp[v])+abs(a[u]-a[u'])\) 其中\(v\)是\(u\)的儿子。
交换: \(dp[u]=max(dp[v']+abs(a[u]-a[u']))\) 其中\(v'\)是\(u'\)的儿子。
若只有第一个式子就很好求,考虑第二个式子:
\(v'\)跟\(u'\)是联系起来的,于是拆abs括号,改为\(max(dp[v']-a[u']+a[u],dp[v']+a[u']-a[u])\)
然后我们就需要知道类似同层v'的mxson,然后按上面存一下。
于是先dfs一遍,记录每层信息。
再按层从下往上便历求解dp
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+5;
typedef long long ll;
ll dp[N],a[N],mx[N],mn0[N],mx0[N];
int D,nxt[N],head[N],fa[N],to[N],ecnt,dep[N],cnt;
vector<int> V[N];
void add_edge(int u,int v) {nxt[++ecnt]=head[u];to[ecnt]=v;head[u]=ecnt;}
void dfs1(int u) {
dep[u]=dep[fa[u]]+1;
cnt++;
mx0[dep[u]]=max(mx0[dep[u]],a[u]);
mn0[dep[u]]=min(mn0[dep[u]],a[u]);
V[dep[u]].push_back(u);
D=max(D,dep[u]);
for(int i=head[u];i;i=nxt[i]) {
int v=to[i];
if(v==fa[u])continue;
fa[v]=u;
dfs1(v);
}
}
void solve() {
for(int i=D;i>=1;i--) {
ll mx1=-1e18,mx2=-1e18;
for(int q=0;q<V[i].size();q++) {
int u=V[i][q],w=max(abs(a[u]-mx0[dep[u]]),abs(a[u]-mn0[dep[u]]));
if(i==D) {dp[u]=w;continue;}
for(int j=head[u];j;j=nxt[j]) {
int v=to[j];
if(v==fa[u])continue;
mx[u]=max(mx[u],dp[v]);
dp[u]=max(dp[u],dp[v]+w);
}
mx1=max(mx1,mx[u]+a[u]);
mx2=max(mx2,mx[u]-a[u]);
}
if(i!=D) {
for(int q=0;q<V[i].size();q++) {
int u=V[i][q];
dp[u]=max(dp[u],max(mx1-a[u],a[u]+mx2));
// printf("%d: %lld\n",u,dp[u]);
}
}
V[i].clear();
}
}
int main() {
int T,n;
scanf("%d",&T);
while(T--) {
scanf("%d",&n);
ecnt=0;
for(int i=1;i<=n;i++) mn0[i]=1e9,dp[i]=head[i]=mx0[i]=mx[i]=0;
for(int i=2;i<=n;i++) {
int v;
scanf("%d",&v);
add_edge(i,v),add_edge(v,i);
}
for(int i=2;i<=n;i++) scanf("%lld",&a[i]);
dfs1(1);
solve();
printf("%lld\n",dp[1]);
}
return 0;
}
CF1485E Move and Swap的更多相关文章
- swap的几点理解
一.什么是swap space(交换分区)? 在Linux系统中,当物理内存满了才使用Swap空间.当系统需要更多的内存资源,并且物理内存已经满了,此时,内存中那些不活跃的pages被移动(move) ...
- 做个地道的c++程序猿:copy and swap惯用法
如果你对外语感兴趣,那肯定听过"idiom"这个词.牛津词典对于它的解释叫惯用语,再精简一些可以叫"成语".想要掌握一门语言,其中的"成语" ...
- swap分区扩展的三种方法
redhat linux swap分区扩展的三种方法 2016-12-26 11:41:08 分类: LINUX 原文地址:redhat linux swap分区扩展的三种方法 作者:quanshen ...
- uva12545 Bits Equalizer
uva12545 Bits Equalizer You are given two non-empty strings S and T of equal lengths. S contains the ...
- 【转】C++11 标准新特性: 右值引用与转移语义
VS2013出来了,对于C++来说,最大的改变莫过于对于C++11新特性的支持,在网上搜了一下C++11的介绍,发现这篇文章非常不错,分享给大家同时自己作为存档. 原文地址:http://www.ib ...
- C++11智能指针
今晚跟同学谈了一下智能指针,突然想要看一下C++11的智能指针的实现,因此下了这篇博文. 以下代码出自于VS2012 <memory> template<class _Ty> ...
- Codeforces Gym 100203E E - bits-Equalizer 贪心
E - bits-EqualizerTime Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.hust.edu.cn/vjudge/contest ...
- C++11 标准新特性: 右值引用与转移语义
文章出处:https://www.ibm.com/developerworks/cn/aix/library/1307_lisl_c11/ 新特性的目的 右值引用 (Rvalue Referene) ...
- Linux内核入门到放弃-页面回收和页交换-《深入Linux内核架构》笔记
概述 可换出页 只有少量几种页可以换出到交换区,对其他页来说,换出到块设备上与之对应的后备存储器即可,如下所述. 类别为 MAP_ANONYMOUS 的页,没有关联到文件,例如,这可能是进程的栈或是使 ...
随机推荐
- window10解决需要管理员删除文件的权限问题
1.快捷键:"win+R",输入:gpedit.msc 回车 2.依次点击:计算机配置-windows配置-安全设置-本地策略-安全选项 3.将两个管理员批准模式和管理员状态三者 ...
- 单例设计模式(Singleton)
一.单例设计模式介绍 所谓类的单例设计模式,就是采取一定的方法保证在整个的软件系统中,对某个类只能存在一个对象实例, 并且该类只提供一个取得其对象实例的方法(静态方法) 例如:Hibernate的Se ...
- JS 实现权限列表移动
JS 实现列表移动 学习内容: 需求 总结: 学习内容: 需求 用 JS 实现列表移动 实现代码 <html> <head> <meta http-equiv=" ...
- java集合总览
在编写java程序中,我们最常用的除了八种基本数据类型,String对象外还有一个集合类,在我们的的程序中到处充斥着集合类的身影!java中集合大家族的成员实在是太丰富了,有常用的ArrayList. ...
- 记录Jenkins升级到最新版遇到的问题
首先吐槽一下Jenkins: 1.安装插件的时候无法根据Jenkins的版本号安装对应的插件! 2.安装插件安装版本不一致的时候无法降低插件版本! 3.为啥要我们升级到最新版! 一.升级原因 我的 ...
- For-Each循环(增强型For循环)
public class Demo077 { public static void main(String[] args) { int[] array ={11,2}; System.out.prin ...
- 羽夏壳世界—— PE 结构(上)
羽夏壳世界之 PE 结构(上),介绍难度较低的基本 PE 相关结构体.
- 关于物理机没有VMnet1和VMnet8网卡的问题
当我们在用虚拟机做实验需要与物理机进行连接时,发现无法连接上,这时候可能是没有Vmnet1或者Vmnet8网卡,又或者是Vmnet1和Vmnet8网卡都没有. 之前试过很多方法,重装.重启虚拟网络编辑 ...
- 初始celery
使用celery执行异步任务 下载celery,redis pip3 install celery#在这里我使用的是celery==4.2.2#当celery版本过低的话celery配置可能会略有不同 ...
- 【ACM程序设计】最小生成树 Prim算法
最小生成树 ● 最小生成树的定义是给定一个无向图,如果它任意两个顶点都联通并且是一棵树,那么我们就称之为生成树(Spanning Tree).如果是带权值的无向图,那么权值之和最小的生成树,我们就称之 ...