6364. 【NOIP2019模拟2019.9.20】养马
题目描述




题解
一种显然的水法:max(0,-(点权-边权之和*2))
这样会挂是因为在中途体力值可能会更小,所以考虑求走完每棵子树所需的至少体力值
考虑从子树往上推求出当前点的答案
设每棵子树从根往下走的所需体力值为f,走完的贡献为sum
由于要加上 当前点-->儿子 这条边,所以实际上走完的贡献sum'=sum-边权*2
所需的体力值f'=max(边权+f,2*边权-sum),这里其实有两种情况
①当前点-->儿子-->子树(-->儿子),那么最坏情况就是(子树的最坏情况+边权)
②当前点-->儿子-->子树-->儿子-->当前点,最终的贡献实际为sum-边权*2,那么就需要至少max(0,边权*2-sum)的体力
显然对于贡献≥0的点按照需求从小到大取
对于贡献<0的点,定义减少量=-贡献
那么按照需求-减少量从大到小排序即可
证明:
定义差值=需求-减少量
对于两个儿子,设第一个儿子的差值和减少量分别为a和b,第二个为cd
先假设已经按照差值排序,且排序后两个儿子相邻,那么有a≥c
证明交换后不会更优
设x为走这两棵子树前的体力,保证在中途不会出现负数且能达到需求量
那么有
交换前:
x≥a+b,x-b≥c+d
交换后:
x≥c+d,x-d≥a+b
根据式子
根节点贡献+恢复的体力-每棵子树的减少量之和=剩余体力,其中只有恢复的体力是变量,所以可以发现剩余体力越少=答案越小
由于交换前后剩余的体力都是x-b-d,所以要使x尽量小(太大可能会导致有剩余)
所以变成证明
max(a+b,b+c+d)≤max(c+d,a+b+d)
由于a+b+d≤max(c+d,a+b+d),且a+b+d≥a+b和b+c+d(a≥c),所以max(a+b,b+c+d)≤a+b+d≤max(c+d,a+b+d)
得证
code
#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#define fo(a,b,c) for (a=b; a<=c; a++)
#define fd(a,b,c) for (a=b; a>=c; a--)
#define min(a,b) (a<b?a:b)
#define max(a,b) (a>b?a:b)
using namespace std;
struct type{
long long f,sum;
} b[100001],c[100001];
int a[200001][3];
int ls[100001];
int w[100001];
long long f[100001];
long long sum[100001];
int n,i,j,k,l,len;
long long ans;
bool cmp(type a,type b)
{
return a.f<b.f;
}
bool Cmp(type a,type b)
{
return a.f-a.sum>b.f-b.sum;
}
void New(int x,int y,int z)
{
++len;
a[len][0]=y;
a[len][1]=ls[x];
a[len][2]=z;
ls[x]=len;
}
void dfs(int Fa,int t)
{
int i,l1=0,l2=0;
long long now=w[t];
sum[t]=w[t];
for (i=ls[t]; i; i=a[i][1])
if (a[i][0]!=Fa)
{
dfs(t,a[i][0]);
sum[t]+=sum[a[i][0]]-a[i][2]-a[i][2];
}
if (!ls[t]) return;
for (i=ls[t]; i; i=a[i][1])
if (a[i][0]!=Fa)
{
if (sum[a[i][0]]-a[i][2]-a[i][2]>=0)
{
++l1;
b[l1].f=max(f[a[i][0]]+a[i][2],-(sum[a[i][0]]-a[i][2]-a[i][2]));
b[l1].sum=sum[a[i][0]]-a[i][2]-a[i][2];
}
else
{
++l2;
c[l2].f=max(f[a[i][0]]+a[i][2],-(sum[a[i][0]]-a[i][2]-a[i][2]));
c[l2].sum=-(sum[a[i][0]]-a[i][2]-a[i][2]);
}
}
if (l1)
{
sort(b+1,b+l1+1,cmp);
fo(i,1,l1)
{
if (now<b[i].f)
{
f[t]+=b[i].f-now;
now=b[i].f;
}
now+=b[i].sum;
}
}
if (l2)
{
sort(c+1,c+l2+1,Cmp);
if (now<(c[1].f-c[1].sum))
{
f[t]+=(c[1].f-c[1].sum)-now;
now=0;
}
else
now-=(c[1].f-c[1].sum);
fo(i,1,l2)
{
if (i>1)
now+=(c[i-1].f-c[i-1].sum)-(c[i].f-c[i].sum);
if (now<c[i].sum)
{
f[t]+=c[i].sum-now;
now=c[i].sum;
}
now-=c[i].sum;
}
}
}
int main()
{
// freopen("a.in","r",stdin);
// freopen("b.out","w",stdout);
freopen("horse.in","r",stdin);
freopen("horse.out","w",stdout);
scanf("%d",&n);
fo(i,1,n)
scanf("%d",&w[i]);
fo(i,2,n)
{
scanf("%d%d%d",&j,&k,&l);
New(j,k,l);
New(k,j,l);
}
dfs(0,1);
printf("%lld\n",f[1]);
fclose(stdin);
fclose(stdout);
return 0;
}
6364. 【NOIP2019模拟2019.9.20】养马的更多相关文章
- NOIP2019模拟2019.9.20】膜拜大会(外向树容斥,分类讨论)
传送门. 题解: 我果然是不擅长分类讨论,心态被搞崩了. 注意到\(m<=n-2\),意味着除了1以外的位置不可能被加到a[1]两遍. 先考虑个大概: 考虑若存在\(x,x-1,-,2\)(有序 ...
- 6359. 【NOIP2019模拟2019.9.15】小ω的树(tree)(定期重构)
题目描述 题解 qy的毒瘤题 CSP搞这种码农题当场手撕出题人 先按照边权从大到小建重构树,然后40%暴力修改+查找即可 100%可以定期重构+平衡规划,每次把B个询问拉出来建虚树,在虚树上暴力维护每 ...
- [JZOJ6075]【GDOI2019模拟2019.3.20】桥【DP】【线段树】
Description N,M<=100000,S,T<=1e9 Solution 首先可以感受一下,我们把街道看成一行,那么只有给出的2n个点的纵坐标是有用的,于是我们可以将坐标离散化至 ...
- 6424. 【NOIP2019模拟2019.11.13】我的订书机之恋
题目描述 Description Input Output Sample Input 见下载 Sample Output 见下载 Data Constraint 题解 lj题卡线段树 求出每个右端点往 ...
- 6392. 【NOIP2019模拟2019.10.26】僵尸
题目描述 题解 吼题但题解怎么这么迷 考虑一种和题解不同的做法(理解) 先把僵尸离散化,h相同的钦(ying)点一个大小 (可以发现这样每种情况只会被算正好一次) 计算完全被占领的方案,然后1-方案/ ...
- 6389. 【NOIP2019模拟2019.10.26】小w学图论
题目描述 题解 之前做过一次 假设图建好了,设g[i]表示i->j(i<j)的个数 那么ans=∏(n-g[i]),因为连出去的必定会构成一个完全图,颜色互不相同 从n~1染色,点i的方案 ...
- 6377. 【NOIP2019模拟2019.10.05】幽曲[埋骨于弘川]
题目描述 题解 随便bb 详细题解见 https://www.cnblogs.com/coldchair/p/11624979.html https://blog.csdn.net/alan_cty/ ...
- 6362. 【NOIP2019模拟2019.9.18】数星星
题目描述 题解 一种好想/好写/跑得比**记者还快的做法: 对所有询问排序,按照R递增的顺序来处理 维护每个点最后一次被覆盖的时间,显然当前右端点为R时的答案为所有时间≥L的点的权值之和 LCT随便覆 ...
- 【NOIP2019模拟2019.11.13】旅行 && GDKOI2018 还念(二分答案+dij)
Description: 题解: 显然满足二分性. 并且每一条边要不选l要不选r. 二分的那条链肯定要选l. 考虑有两个人在走最短路,一个人一开始必须走二分的那条链,要求第一个人走的比第二个人快. 安 ...
随机推荐
- 关于在DBGridEh的一个字段使用checkbox的方法 .
在DBGridEh的columns中新增加一个字段 1.如果你选择的数据库字段,则选择checkbox为true,并在keylist中输入0和1,就可以了 2.如果你选择的是一个临时字段,在数据集中新 ...
- 安装golang web框架 gin
gin 地址https://github.com/gin-gonic/gin#installation 去gin 地址 clone 下来,放到对应的包中即可.如:gin就放在项目文件夹/github. ...
- vim加脚本注释和文本加密
vim /etc/vimrc 一.李导版本 autocmd BufNewFile *.py,*.cc,*.sh,*.java exec ":call SetTitle()" fun ...
- mysql驱动表与被驱动表及join优化
驱动表与被驱动表 先了解在join连接时哪个表是驱动表,哪个表是被驱动表:1.当使用left join时,左表是驱动表,右表是被驱动表2.当使用right join时,右表时驱动表,左表是驱动表3.当 ...
- [转帖]linux screen 命令详解,xshell关掉窗口或者断开连接,查看断开前执行的命令
linux screen 命令详解,xshell关掉窗口或者断开连接,查看断开前执行的命令 https://binwaer.com/post/12.html yun install -y screen ...
- MySQL-快速入门(11)用户管理
1.权限表 存储用户权限信息表主要有:user.db.host.tables_priv.columns_priv.procs_priv. 1>user表: 记录允许连接到服务器的账号信息,里面的 ...
- Python 入门之 文件
Python 入门之 文件 1.文件操作 找到文件位置 双击打开 进行一些操作 r-read(读) w-write(写) a-追加 rd--读字节 wd--清空写,写字节 ad --追加写(字节) r ...
- css是干什么的
css这些长篇累牍的参数,其实就是这些所谓的css编程者每天要干的事情了,他们把这些参数熟记于心,就像c++程序员,把这些函数库熟记于心一样,都是编程. css定制了每一个单独的组件,这些组件要么是相 ...
- W3C标准下的盒模型与IE盒模型
标准盒模型如下图所示: IE下盒模型如下图所示:
- 解决stanfordnlp一直运行不报错也没有结果
最近学习stanfordnlp,当运行程序时,发现程序一直没有反应,上网查询说是内存不够,但是本地电脑是8g内存.后来重新下载了所需文件,问题解决.