题面在这里

题意

一个王国中的所有城市构成了一棵有根树,其根节点为首都,编号为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. 2017年PHP程序员未来路在何方?(转载)

    PHP 从诞生到现在已经有 20 多年历史,从 Web 时代兴起到移动互联网退潮,互联网领域各种编程语言和技术层出不穷, Node.js . GO . Python 不断地在挑战 PHP 的地位.这些 ...

  2. .Net Core On Liunx 环境搭建之 Docker 容器和Nginx

    上一篇文章安装了Mysql8数据库,接下开始安装Docker和Nginx 我的思路是这样的,用Docker当运行环境的虚拟机,Nginx当Http服务器用来做反向代理. 服务器环境:阿里云服务器,操作 ...

  3. php柱状图多系列动态实现

    <?php require_once 'data.php'; require_once 'jpgraph/src/jpgraph.php'; require_once"jpgraph/ ...

  4. 【PHP项目】产品新增的多图上传

    产品新增:多图上传 1:html的更改 在 type=file的input框中添加multiple="multiple" name属性中必须添加[] ,否则$_FILES只能接收最 ...

  5. Python学习:1.快速搭建python环境

    一.安装python 现在python有两个比较大的版本一个是python3.x一个是python2.x,python3.x相当于与python2.x是一个比较大的升级,但是python3.x没有向下 ...

  6. Redis缓存数据库的安装与配置(1)

    1.安装 tarxf redis-3.2.5.tar.gz cd redis-3.2.5 make mkdir -p /usr/local/redis/bin src目录下这些文件作用如下 redis ...

  7. Make命令完全详解教程

    Make命令完全详解教程 无论是在Linux还是在Unix环境中,make都是一个非常重要的编译命令.不管是自己进行项目开发还是安装应用软件,我们都经常要用到make或make install.利用m ...

  8. Java线程和多线程(九)——死锁

    Java中的死锁指的就是一种多于两个线程永远阻塞的特殊状况.Java中的死锁状态至少需要多于两个线程以及资源的时候才会产生.这里,我写了一个产生死锁的程序,并且讲下如何分析死锁. 首先来看一下产生死锁 ...

  9. ExtJs工具篇(2)——Aptana Studio 3 汉化

    本身用的是中文版本的,但是输入一些中文后,竟然有乱码,所以就想把它汉化.在网上搜索了一下,把步骤记录如下: 首先到这个网站去 http://aptana.com/support 选择View Docu ...

  10. html简单的分享功能

    超级简单的分享. 包括:QQ.QQ空间.新浪微博.腾讯微博,微信(只是一个二维码): 1.首先是html代码: (前端我并不太会,一直用的都是bootstrap) <div class=&quo ...