[CSP-S模拟测试]:Park(树上DP)
题目描述
公园里有$n$个雕像,有$n-1$条道路分别连接其中两个雕像,任意两个雕像可以直接或间接相连。现在每个景点$i$聚集着$P_i$只鸽子,旅行家手里有$v$数量的面包屑。
一旦旅行家在雕像$i$撒下$1$单位面包屑,那么相邻的雕像的鸽子就都会飞到雕像$i$来觅食。
时间线是这样的:首先,旅行家到达雕像$i$并与$P_i$鸽子会面。然后,他放下$1$单位面包屑。他离开雕像。在旅行家到达下一座雕像之前,来自相邻雕像的鸽子移动到雕像$i$(所以这些鸽子不计入他遇到的鸽子数)。注意旅行家每到一达雕像可以撒下面包屑,也可以不撒。
旅行家可以在任何一座雕像上进入公园,沿着一些道路走下去(但不要使用同一道路两次),然后离开公园。
在旅行家离开公园后,没有面包屑的小学生将进入并穿越完全相同的路线,并遇见许多群鸽子。
通过最多$v$单位面包屑,旅行家希望最大化旅行家在路线上遇到的鸽子数量与小学生遇到的鸽子数量之间的差异。
输入格式
第一行两个整数$n,v$
第二行$n$个数为$P_i$
接下来$n-1$,每行两个整数,$X_i,Y_i$表示$X_i$与$Y_i$雕像相连
输出格式
输出只有一行,表示答案
样例
样例输入:
12 2
2 3 3 8 1 5 6 7 8 3 5 4
2 1
2 7
3 4
4 7
7 6
5 6
6 8
6 9
7 10
10 11
10 12
样例输出:
36
数据范围与提示
样例解释:
一个可行的方案:旅行家从雕像$6$进入公园。在那里他遇到了$5$只鸽子。他放下面包屑。$p_6$现在是$27$,$p_5=p_7=p_8=p_9=0$。接下来,他跑向雕像$7$并遇到$0$鸽子。他撒下了第二个面包屑。$p_7=41$且$p_2=p_4=p_6=p_{10}=0$。他离开公园,他总共遇见$5+0=5$只鸽子。小学生跟着他走过同样的路线,但遇到$p_6+p_7=0+41=41$只鸽子。差是$41-5=36$。
数据范围:
对于$20\%$的数据,$1\leqslant n\leqslant 10$
对于另外$20\%$的数据,$1\leqslant n\leqslant 1,000$
对于另外$30\%$的数据,存在一个可行的最优方案从$1$出发
对于另外$30\%$的数据无特殊限制
对于$100\%$的数据,$1\leqslant n\leqslant 10^5,0\leqslant v\leqslant 100,0\leqslant P_i\leqslant 10^9$
题解
原题见$CEOI2017\ Chase$,我也不知道玄学出题人改的什么玄学题面……
一看就是$DP$题,但是显然我们不能枚举起点。
但是我们还是要先想一下枚举端点的做法,做事要慢慢来~
我的做法是设$dp[i][j][0/1]$表示到了$i$号点,已经撒了$j$次,在当前节点有没有撒的最大收益,转移是这样的:
$$dp[i][j][0]=max(dp[fa][j][0],dp[fa][j][1]) \\ dp[i][j][1]=max(dp[fa][j-1][0],dp[fa][j-1][1])+sum[i]-p[fa]$$
其中$sum[i]$表示在$i$号点撒会引来$sum[i]$只鸽子,不含$i$号点本身就有的,如下图$\downarrow$
$sum[i]$是指$\sum \limits_{i=1}^4 p_i$。
直接这样做会$TLE\ 44$,如果我们加上$clock()$的话可以得到$74\sim 78$不等。
那么我们现在考虑满分解法,如何快速求出以每个点为起点的最大贡献,将其取$\max$即可。
考虑定义两个数组$up[i][j]$和$down[i][j]$分别表示从$i$的子树走向$i$和从$i$走向$i$的子树,撒了$j$次的最大贡献。
然后状态转移是这样的:
$$up[i][j]=\max(up[i][j],up[son][j],up[son][j-1]+sum[i]-p[son]) \\ down[i][j]=\max(down[i][j],down[son][j],down[son][j-1]+sum[i]-p[fa])$$
还需要注意一点,如下图$\downarrow$
两种走法的最大贡献不一定相等,于是我们要正序枚举一遍所有的儿子,再倒着枚举一遍即可。
时间复杂度:$\Theta(n\times v)$。
期望得分:$100$分。
实际得分:$100$分。
代码时刻
#include<bits/stdc++.h>
using namespace std;
int n,v;
int p[100001];
long long sum[100001];
long long dp[2][100001][101];
long long ans;
vector<int> e[100001];
void dfs(int x,int fa)
{
for(int i=1;i<=v;i++)
{
dp[0][x][i]=sum[x];
dp[1][x][i]=sum[x]-p[fa];
}
for(int i=0;i<e[x].size();i++)
if(e[x][i]!=fa)
{
dfs(e[x][i],x);
for(int j=1;j<v;j++)ans=max(ans,dp[0][x][j]+dp[1][e[x][i]][v-j]);
for(int j=1;j<=v;j++)
{
dp[0][x][j]=max(dp[0][x][j],max(dp[0][e[x][i]][j],dp[0][e[x][i]][j-1]+sum[x]-p[e[x][i]]));
dp[1][x][j]=max(dp[1][x][j],max(dp[1][e[x][i]][j],dp[1][e[x][i]][j-1]+sum[x]-p[fa]));
}
}
reverse(e[x].begin(),e[x].end());
for(int i=1;i<=v;i++)
{
dp[0][x][i]=sum[x];
dp[1][x][i]=sum[x]-p[fa];
}
for(int i=0;i<e[x].size();i++)
if(e[x][i]!=fa)
{
for(int j=1;j<v;j++)ans=max(ans,dp[0][x][j]+dp[1][e[x][i]][v-j]);
for(int j=1;j<=v;j++)
{
dp[0][x][j]=max(dp[0][x][j],max(dp[0][e[x][i]][j],dp[0][e[x][i]][j-1]+sum[x]-p[e[x][i]]));
dp[1][x][j]=max(dp[1][x][j],max(dp[1][e[x][i]][j],dp[1][e[x][i]][j-1]+sum[x]-p[fa]));
}
}
ans=max(ans,max(dp[0][x][v],dp[1][x][v]));
}
int main()
{
scanf("%d%d",&n,&v);if(!v){puts("0");return 0;}
for(int i=1;i<=n;i++)scanf("%d",&p[i]);
for(int i=1;i<n;i++)
{
int x,y;
scanf("%d%d",&x,&y);
e[x].push_back(y);
e[y].push_back(x);
sum[x]+=p[y];
sum[y]+=p[x];
}
dfs(1,0);
printf("%lld",ans);
return 0;
}
rp++
[CSP-S模拟测试]:Park(树上DP)的更多相关文章
- [CSP-S模拟测试]:B(DP+数学)
题目传送门(内部题45) 输入格式 第一行$3$个整数$n,m,P$.第二行$m$个整数,表示$m$次询问. 输出格式 一行$m$个整数表示答案. 样例 样例输入1: 2 4 40 1 2 3 样例输 ...
- [CSP-S模拟测试]:蛇(DP+构造+哈希)
题目传送门(内部题140) 输入格式 前两行有两个长度相同的字符串,描述林先森花园上的字母. 第三行一个字符串$S$. 输出格式 输出一行一个整数,表示有多少种可能的蛇,对$10^9+7$取模. 样例 ...
- [CSP-S模拟测试]:最小值(DP+乱搞)
题目背景 $Maxtir$更喜欢序列的最小值. 题目传送门(内部题128) 输入格式 第一行输入一个正整数$n$和四个整数$A,B,C,D$. 第二行输入$n$个整数,第$i$个数表示$a_i$. 输 ...
- [CSP-S模拟测试]:花(DP)
题目传送门(内部题111) 输入格式 一个整数$T$,表示测试数据组数. 每组测试数据占一行,两个整数,分别表示$L$和$S$. 输出格式 对每组数据,输出一个整数表示答案. 样例 样例输入1: 13 ...
- [CSP-S模拟测试]:计数(DP+记忆化搜索)
题目描述 既然是萌萌哒$visit\text{_}world$的比赛,那必然会有一道计数题啦!考虑一个$N$个节点的二叉树,它的节点被标上了$1\sim N$的编号.并且,编号为$i$的节点在二叉树的 ...
- [CSP-S模拟测试]:matrix(DP)
题目描述 求出满足以下条件的$n\times m$的$01$矩阵个数:(1)第$i$行第$1~l_i$列恰好有$1$个$1$.(2)第$i$行第$r_i~m$列恰好有$1$个$1$.(3)每列至多有$ ...
- [CSP-S模拟测试]:题(DP+数学)
题目描述 出个题就好了.这就是出题人没有写题目背景的原因.你在平面直角坐标系上.你一开始位于$(0,0)$.每次可以在上/下/左/右四个方向中选一个走一步.即:从$(x,y)$走到$(x,y+1),( ...
- [CSP-S模拟测试]:题(DP)
题目描述 由于出题人赶时间所以没办法编故事来作为背景.一开始有$n$个苹果,$m$个人依次来吃苹果,第$i$个人会尝试吃$u_i$或$v_i$号苹果,具体来说分三种情况.$\bullet 1.$两个苹 ...
- [CSP-S模拟测试]:y(DP+bitset)
题目背景 $\frac{1}{4}$遇到了一道水题,叕完全不会做,于是去请教小$D$.小$D$懒得理$\frac{1}{4}$,直接就离开了.于是,$\frac{1}{4}$只好来问你,这道题是这样的 ...
随机推荐
- scrapy爬取booking酒店评论数据
# scrapy爬取酒店评论数据 -- 代码 here:github地址:https://github.com/760730895/scrapy_Booking-- 采用scrapy爬取酒店评论数据 ...
- Mac018--VisualBox & ubuntu 安装
一.安装虚拟机VMware 参考博客:https://blog.csdn.net/u013142781/article/details/50529030 Step1:下载ubuntu镜像 注:选择Ub ...
- 如何理解ajax的同步和异步?
对于如下一段代码: var dataJson = {"ABC":'testABC'}; $.ajax({ url: "/MonkeyServ ...
- [2019杭电多校第一场][hdu6579]Operation(线性基)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6579 题目大意是两个操作,1个是求[l,r]区间子序列的最大异或和,另一个是在最后面添加一个数. 如果 ...
- HDU2188选拔自愿者
悼念512汶川大地震遇难同胞--选拔志愿者 Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Ot ...
- 洛咕 【P1891】疯狂LCM & 三倍经验
经验给掉先: 经验*1 经验*2 经验*3 这里给个跑得比较慢的 \(n \sqrt n\) 预处理然后 \(O(1)\) 回答询问的做法 式子 首先我们推柿子: \[\begin{aligned}A ...
- vscode加MinGw三步搭建c/c++调试环境
vscode加MinGw三步搭建c/c++调试环境 step1:安装vscode.MinGw 1.1 vscod常规安装:https://code.visualstudio.com/ 1.2 MinG ...
- 输入某人出生日期(以字符串方式输入,如1987-4-1)使用DateTime和TimeSpan类,(1)计算其人的年龄;(2)计算从现在到其60周岁期间,总共多少天。
http://blog.csdn.net/w92a01n19g/article/details/8764116 using System;using System.Collections.Generi ...
- (一)WebPack4.0 从零开始
一:WebPack基础知识 (1):webpack的定义 webpack官网给出的定义是:webpack 是一个现代 JavaScript 应用程序的静态模块打包器(module bundler). ...
- 5-基于TMS320C6678+XC7K325T的6U CPCIe高性能处理平台
基于TMS320C6678+XC7K325T的6U CPCIe高性能处理平台 一.板卡概述 本板卡系自主研发,基于CPCI 6U架构,符合CPCI2.0标准.采用 DSP TMS320C66 ...