题目描述







题解

一种显然的水法: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】养马的更多相关文章

  1. NOIP2019模拟2019.9.20】膜拜大会(外向树容斥,分类讨论)

    传送门. 题解: 我果然是不擅长分类讨论,心态被搞崩了. 注意到\(m<=n-2\),意味着除了1以外的位置不可能被加到a[1]两遍. 先考虑个大概: 考虑若存在\(x,x-1,-,2\)(有序 ...

  2. 6359. 【NOIP2019模拟2019.9.15】小ω的树(tree)(定期重构)

    题目描述 题解 qy的毒瘤题 CSP搞这种码农题当场手撕出题人 先按照边权从大到小建重构树,然后40%暴力修改+查找即可 100%可以定期重构+平衡规划,每次把B个询问拉出来建虚树,在虚树上暴力维护每 ...

  3. [JZOJ6075]【GDOI2019模拟2019.3.20】桥【DP】【线段树】

    Description N,M<=100000,S,T<=1e9 Solution 首先可以感受一下,我们把街道看成一行,那么只有给出的2n个点的纵坐标是有用的,于是我们可以将坐标离散化至 ...

  4. 6424. 【NOIP2019模拟2019.11.13】我的订书机之恋

    题目描述 Description Input Output Sample Input 见下载 Sample Output 见下载 Data Constraint 题解 lj题卡线段树 求出每个右端点往 ...

  5. 6392. 【NOIP2019模拟2019.10.26】僵尸

    题目描述 题解 吼题但题解怎么这么迷 考虑一种和题解不同的做法(理解) 先把僵尸离散化,h相同的钦(ying)点一个大小 (可以发现这样每种情况只会被算正好一次) 计算完全被占领的方案,然后1-方案/ ...

  6. 6389. 【NOIP2019模拟2019.10.26】小w学图论

    题目描述 题解 之前做过一次 假设图建好了,设g[i]表示i->j(i<j)的个数 那么ans=∏(n-g[i]),因为连出去的必定会构成一个完全图,颜色互不相同 从n~1染色,点i的方案 ...

  7. 6377. 【NOIP2019模拟2019.10.05】幽曲[埋骨于弘川]

    题目描述 题解 随便bb 详细题解见 https://www.cnblogs.com/coldchair/p/11624979.html https://blog.csdn.net/alan_cty/ ...

  8. 6362. 【NOIP2019模拟2019.9.18】数星星

    题目描述 题解 一种好想/好写/跑得比**记者还快的做法: 对所有询问排序,按照R递增的顺序来处理 维护每个点最后一次被覆盖的时间,显然当前右端点为R时的答案为所有时间≥L的点的权值之和 LCT随便覆 ...

  9. 【NOIP2019模拟2019.11.13】旅行 && GDKOI2018 还念(二分答案+dij)

    Description: 题解: 显然满足二分性. 并且每一条边要不选l要不选r. 二分的那条链肯定要选l. 考虑有两个人在走最短路,一个人一开始必须走二分的那条链,要求第一个人走的比第二个人快. 安 ...

随机推荐

  1. golang 千位分隔符

    项目需求将统计出的数字以千位分隔符分隔的形式展示(如将 1234567.89 格式化为 1,234,567.89),而 golang 的标准库中并无这样的函数. 万能的 google 找到解决办法,可 ...

  2. nginx重要特性

    反向代理负载均衡实现高并发 1.反向代理反向代理(Reverse Proxy)方式是指以代理服务器来接受Internet上的连接请求,然后将请求转发给内部网络上的服务器:并将从服务器上得到的结果返回给 ...

  3. HTML5 列表、表格、媒体元素

    无序列表 <ul> <li>范冰冰演藏族女孩</li> <li>拍集体合影后自拍</li> <li>诗隆甜蜜出游</li& ...

  4. python string_1

    quote :http://www.runoob.com/python/python-strings.html #coding:utf-8 s1="http://www.jnshu.com/ ...

  5. python中的各个模块

    collection模块:python中的扩展数据模块#namedtuple: 生成可以使用名字来访问元素内容的tuple'''from collections import namedtuplePo ...

  6. 【监控笔记】【2.4】SQL Server中的 Ring Buffer 诊断各种系统资源压力情况

    SQL Server 操作系统(SQLOS)负责管理特定于SQL Server的操作系统资源. 其中相关的动态管理试图sys.dm_os_ring_buffers将被标识为仅供参考.不提供支持.不保证 ...

  7. MySQL-快速入门(7)索引

    1.什么是索引 索引是对数据库表中一列或者多列的值进行排序的一种结构.索引是在存储引擎中实现的,每种存储引擎中的索引不一定完全相同. MySQL中索引的存储类型有两种:btree和hash.MyISA ...

  8. win10上安装redis

    1.下载安装包: 下载地址: 链接:https://pan.baidu.com/s/1oGPrfQJvFz-fX_KNcTTNUw 提取码:eake 2.在适合的位置创建一个文件夹,并将下载到的压缩包 ...

  9. 深度学习之depthwise separable convolution,计算量及参数量

    目录: 1.什么是depthwise separable convolution? 2.分析计算量.flops 3.参数量 4.与传统卷积比较 5.reference

  10. vscode 将本地项目上传到码云

    **************************************************************************************************** ...