题面在这里

题意

一个王国中的所有城市构成了一棵有根树,其根节点为首都,编号为1

树有边权,城市的记者每次向祖先移动\(d\)的路程需要的代价为\(d^2\),

如果祖先不是根还需要加上\(p\),求每个非根节点的记者移动到首都的最小代价

sol

考虑朴素的DP,设\(f[i]\)表示第\(i\)号节点到达根节点的最小代价,

\(s[i]\)表示\(i\)到根节点的距离,那么有

\[f[i]=min_{j\in ancestor(i)}(f[j]+(s[i]-s[j])^2+p)
\]

初始状态为\(f[1]=-p\)

斜率优化:

\[f[i]=min_{j\in ancestor(i)}(f[j]+s[j]^2-2s[i]s[j])+s[i]^2+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的更多相关文章

  1. 《The Elder Scrolls V: Skyrim》百般冷门却强力职业

    <The Elder Scrolls V: Skyrim>百般冷门却强力职业 1.有如成龙平常的杂耍型战斗窃贼 每次看帖都察觉大伙一贯在强调窃贼不需要防御,窃贼不需要血,窃贼就是一击致命, ...

  2. 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] 斜率 ...

  3. HDU 5956 The Elder (树上斜率DP)

    题意:给定上一棵树,然后每条边有一个权值,然后每个点到 1 的距离有两种,第一种是直接回到1,花费是 dist(1, i)^2,还有另一种是先到另一个点 j,然后两从 j 向1走,当然 j 也可以再向 ...

  4. HDU - 59562016ACM/ICPC亚洲区沈阳站I - The Elder 树上斜率优化dp

    题意:给定上一棵树,然后每条边有一个权值,然后每个点到 1 的距离有两种,第一种是直接回到1,花费是 dist(1, i)^2,还有另一种是先到另一个点 j,然后两从 j 向1走,当然 j 也可以再向 ...

  5. 【HDOJ5956】The Elder(树形DP,斜率优化)

    题意:有一棵n个点的有根树,每条边上有一个边权.给定P,从i跳到它的祖先j的费用是距离的平方+P,问所有点中到根节点1的总花费最大值 n<=1e5,p<=1e6,w<=1e2 思路: ...

  6. The Elder HDU - 5956

    /* 树上斜率优化 一开始想的是构造出一个序列 转化成一般的dp但是可能被卡 扫把状的树的话可能变成n*n 其实可以直接在树上维护这个单调队列 dfs虽然搞得是一棵树,但是每次都是dfs到的都是一个序 ...

  7. ACM-ICPC 2016 沈阳赛区现场赛 I. The Elder && HDU 5956(斜率DP)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5956 题意:一颗树上每条边有个权值,每个节点都有新闻要送到根节点就是1节点,运送过程中如果不换青蛙就是 ...

  8. LuoguP7369 [COCI2018-2019#4] Elder 题解

    Content 有一个魔杖最初在 \(Z\) 巫师中.经过 \(n\) 轮较量,第 \(i\) 轮中,\(Z_{i,1}\) 巫师打败了 \(Z_{i,2}\) 巫师.如果一个巫师打败了拥有魔杖的巫师 ...

  9. poj 1251 Jungle Roads (最小生成树)

    poj   1251  Jungle Roads  (最小生成树) Link: http://poj.org/problem?id=1251 Jungle Roads Time Limit: 1000 ...

随机推荐

  1. vue 导出流文件excel

    第一种方法:需要设置响应类型,这里还需要安装 npm install js-file-download --save ,然后引用 var fileDownload = require('js-file ...

  2. Java : java基础(2) 集合&正则&异常&File类

    Obj 方法: hashCode() 返回内存地址值, getClass() 返回的时运行时类, getName() 返回类名, toString() 把名字和hashCode() 合在一起返回,如果 ...

  3. C++ 指针初始化要注意的地方

    1. 声明多个指针的时候: int* P1,P2; 如上所示,声明的是创建一个指针P1和一个int型的变量P2.而不是声明的两个指针. 对每个指针变量名,都需要使用一个*. 在C++中,int* 是一 ...

  4. python2.7练习小例子(十三)

        13):题目:将一个正整数分解质因数.例如:输入90,打印出90=2*3*3*5.     程序分析:对n进行分解质因数,应先找到一个最小的质数k,然后按下述步骤完成.(1)如果这个质数恰等于 ...

  5. 4 class类 web服务器

    1.换行符 2.pycharm 连接Ubuntu 1)添加环境变量 2)查看ip 3)配置目录 4)上传或者下载 3.面向对象抽象web服务器 1)版本1:类 class HttpServer(obj ...

  6. Python的异常

    一.异常的常用形式 异常即是一个事件,该事件会在程序执行过程中发生,影响了程序的正常执行.一般情况下,在Python无法正常处理程序时就会发生一个异常.异常是Python对象,表示一个错误.当Pyth ...

  7. AD-Powershell for Active Directory Administrators

    Table of Contents   Computer object commands Group object commands Organizational Unit (OU) commands ...

  8. Python 3基础教程20-Python中导入模块和包

    本文介绍Python中导入模块和包 #目录: # 导入模块和包--- # | # 上级包.上级模块.导入模块和包的init模块----- # | # 同级包.同级模块.上级包的init模块.test模 ...

  9. ADB常用指令

    adb 命令是adb程序自带的一些命令:adb shell则是调用Android系统的命令,Android系统特有的命令都放在Android设备的/system/bin目录中 MonkeyRunner ...

  10. 可以完成99%的静态页面的HTML标签

    HTML:一套浏览器认知的规则HTML分为两个部分,头和身体.一个完整的网页相当于一个裸体的人,我们利用HTML给它穿上衣服,使它更好看.下面我将为大家介绍一下HTML一些基本的标签,而这些基本的标签 ...