[HDU5956]The Elder
题面在这里
题意
一个王国中的所有城市构成了一棵有根树,其根节点为首都,编号为1
树有边权,城市的记者每次向祖先移动\(d\)的路程需要的代价为\(d^2\),
如果祖先不是根还需要加上\(p\),求每个非根节点的记者移动到首都的最小代价
sol
考虑朴素的DP,设\(f[i]\)表示第\(i\)号节点到达根节点的最小代价,
\(s[i]\)表示\(i\)到根节点的距离,那么有
\]
初始状态为\(f[1]=-p\)
斜率优化:
\]
那么考虑插点\((2s[j],f[j]+s[j]^2)\),询问斜率\(k_i=s[i]\);
树上斜率优化——可持久化单调队列
由于是在树上做,那么我们需要支持撤销前一次的操作;
我们对于记录一个栈,记录推到这个节点时弹出了哪些节点,
撤回的时候在队列中删掉当前节点,把之前弹出的节点放回去即可
这样的时间复杂度应该仍为\(O(n)\)
代码
#include<bits/stdc++.h>
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<iomanip>
#include<cstring>
#include<complex>
#include<vector>
#include<cstdio>
#include<string>
#include<bitset>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<set>
#define mp make_pair
#define pub push_back
#define puf push_front
#define pob pop_back
#define pof pop_front
#define RG register
#define il inline
using namespace std;
typedef unsigned long long ull;
typedef vector<int>VI;
typedef long long ll;
typedef double dd;
const dd eps=1e-10;
const int mod=1e8;
const int N=1000010;
il ll read(){
RG ll data=0,w=1;RG char ch=getchar();
while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
if(ch=='-')w=-1,ch=getchar();
while(ch<='9'&&ch>='0')data=data*10+ch-48,ch=getchar();
return data*w;
}
il void file(){
freopen(".in","r",stdin);
freopen(".out","w",stdout);
}
ll T,n,p,f[N],s[N];
int head[N],nxt[N<<1],to[N<<1],val[N<<1],cnt;
il void add(ll u,ll v,ll w){
to[++cnt]=v;
nxt[cnt]=head[u];
val[cnt]=w;
head[u]=cnt;
}
int L=1,R;ll qx[N],qy[N];
int cal[N],top;ll calx[N],caly[N];
il void cancel(int u){
R--;
while(cal[top]==u){
R++;qx[R]=calx[top];qy[R]=caly[top];top--;
}
}
il void insert(int u,ll x,ll y){
while(L<R&&(qy[R]-qy[R-1])*(x-qx[R])>=(y-qy[R])*(qx[R]-qx[R-1])){
cal[++top]=u;calx[top]=qx[R];caly[top]=qy[R];R--;
}
R++;qx[R]=x;qy[R]=y;
}
il int check(ll k,int mid){
if(mid!=R&&k*(qx[mid+1]-qx[mid])>qy[mid+1]-qy[mid])
return 1;
if(mid!=L&&k*(qx[mid]-qx[mid-1])<qy[mid]-qy[mid-1])
return -1;
return 0;
}
//二分斜率
il ll query(ll k){
RG int l=L,r=R,mid,ret;
while(l<=r){
mid=(l+r)>>1;
ret=check(k,mid);
if(!ret)return qy[mid]-k*qx[mid];
else if(ret==1)l=mid+1;
else if(ret==-1)r=mid-1;
}
}
void dfs_DP(int u,int fa){
if(u!=1){
f[u]=query(s[u])+s[u]*s[u]+p;
insert(u,2*s[u],f[u]+s[u]*s[u]);
}
else insert(u,0,-p);
for(RG int i=head[u];i;i=nxt[i]){
RG int v=to[i];if(v==fa)continue;
s[v]=s[u]+val[i];dfs_DP(v,u);
}
cancel(u);
}
il void solve(){
memset(head,0,sizeof(head));cnt=0;L=1;R=0;
n=read();p=read();
RG ll u,v,w;
for(RG int i=1;i<n;i++){
u=read();v=read();w=read();
add(u,v,w);add(v,u,w);
}
dfs_DP(1,0);
RG ll maxn=0;
for(RG int i=1;i<=n;i++)
maxn=max(maxn,f[i]);
printf("%lld\n",maxn);
}
int main()
{
T=read();while(T--)solve();return 0;
}
[HDU5956]The Elder的更多相关文章
- 《The Elder Scrolls V: Skyrim》百般冷门却强力职业
<The Elder Scrolls V: Skyrim>百般冷门却强力职业 1.有如成龙平常的杂耍型战斗窃贼 每次看帖都察觉大伙一贯在强调窃贼不需要防御,窃贼不需要血,窃贼就是一击致命, ...
- hdu 5956 The Elder
http://acm.hdu.edu.cn/showproblem.php?pid=5956 转移方程:dp[i]=(dis[i]-dis[j])*(dis[i]-dis[j])+P+dp[j] 斜率 ...
- HDU 5956 The Elder (树上斜率DP)
题意:给定上一棵树,然后每条边有一个权值,然后每个点到 1 的距离有两种,第一种是直接回到1,花费是 dist(1, i)^2,还有另一种是先到另一个点 j,然后两从 j 向1走,当然 j 也可以再向 ...
- HDU - 59562016ACM/ICPC亚洲区沈阳站I - The Elder 树上斜率优化dp
题意:给定上一棵树,然后每条边有一个权值,然后每个点到 1 的距离有两种,第一种是直接回到1,花费是 dist(1, i)^2,还有另一种是先到另一个点 j,然后两从 j 向1走,当然 j 也可以再向 ...
- 【HDOJ5956】The Elder(树形DP,斜率优化)
题意:有一棵n个点的有根树,每条边上有一个边权.给定P,从i跳到它的祖先j的费用是距离的平方+P,问所有点中到根节点1的总花费最大值 n<=1e5,p<=1e6,w<=1e2 思路: ...
- The Elder HDU - 5956
/* 树上斜率优化 一开始想的是构造出一个序列 转化成一般的dp但是可能被卡 扫把状的树的话可能变成n*n 其实可以直接在树上维护这个单调队列 dfs虽然搞得是一棵树,但是每次都是dfs到的都是一个序 ...
- ACM-ICPC 2016 沈阳赛区现场赛 I. The Elder && HDU 5956(斜率DP)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5956 题意:一颗树上每条边有个权值,每个节点都有新闻要送到根节点就是1节点,运送过程中如果不换青蛙就是 ...
- LuoguP7369 [COCI2018-2019#4] Elder 题解
Content 有一个魔杖最初在 \(Z\) 巫师中.经过 \(n\) 轮较量,第 \(i\) 轮中,\(Z_{i,1}\) 巫师打败了 \(Z_{i,2}\) 巫师.如果一个巫师打败了拥有魔杖的巫师 ...
- poj 1251 Jungle Roads (最小生成树)
poj 1251 Jungle Roads (最小生成树) Link: http://poj.org/problem?id=1251 Jungle Roads Time Limit: 1000 ...
随机推荐
- vue 导出流文件excel
第一种方法:需要设置响应类型,这里还需要安装 npm install js-file-download --save ,然后引用 var fileDownload = require('js-file ...
- Java : java基础(2) 集合&正则&异常&File类
Obj 方法: hashCode() 返回内存地址值, getClass() 返回的时运行时类, getName() 返回类名, toString() 把名字和hashCode() 合在一起返回,如果 ...
- C++ 指针初始化要注意的地方
1. 声明多个指针的时候: int* P1,P2; 如上所示,声明的是创建一个指针P1和一个int型的变量P2.而不是声明的两个指针. 对每个指针变量名,都需要使用一个*. 在C++中,int* 是一 ...
- python2.7练习小例子(十三)
13):题目:将一个正整数分解质因数.例如:输入90,打印出90=2*3*3*5. 程序分析:对n进行分解质因数,应先找到一个最小的质数k,然后按下述步骤完成.(1)如果这个质数恰等于 ...
- 4 class类 web服务器
1.换行符 2.pycharm 连接Ubuntu 1)添加环境变量 2)查看ip 3)配置目录 4)上传或者下载 3.面向对象抽象web服务器 1)版本1:类 class HttpServer(obj ...
- Python的异常
一.异常的常用形式 异常即是一个事件,该事件会在程序执行过程中发生,影响了程序的正常执行.一般情况下,在Python无法正常处理程序时就会发生一个异常.异常是Python对象,表示一个错误.当Pyth ...
- AD-Powershell for Active Directory Administrators
Table of Contents Computer object commands Group object commands Organizational Unit (OU) commands ...
- Python 3基础教程20-Python中导入模块和包
本文介绍Python中导入模块和包 #目录: # 导入模块和包--- # | # 上级包.上级模块.导入模块和包的init模块----- # | # 同级包.同级模块.上级包的init模块.test模 ...
- ADB常用指令
adb 命令是adb程序自带的一些命令:adb shell则是调用Android系统的命令,Android系统特有的命令都放在Android设备的/system/bin目录中 MonkeyRunner ...
- 可以完成99%的静态页面的HTML标签
HTML:一套浏览器认知的规则HTML分为两个部分,头和身体.一个完整的网页相当于一个裸体的人,我们利用HTML给它穿上衣服,使它更好看.下面我将为大家介绍一下HTML一些基本的标签,而这些基本的标签 ...