[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 ...
随机推荐
- over开窗函数的用法
over(partition by c1.pmid,d1.type,e1.objid order by e1.objid ) pinum 先根据字段排序,pinum.在取第一条数据and p1.pi ...
- C# 多条件拼接sql
#region 多条件搜索时,使用List集合来拼接条件(拼接Sql) StringBuilder sql = new StringBuilder("select * from PhoneN ...
- Hadoop(7)-HDFS客户端的API操作
1 客户端环境准备 根据自己电脑的操作系统拷贝对应的编译后的hadoop jar包到非中文路径 配置HADOOP_HOME的环境变量,并且在path中配置hadoop的bin 重启电脑 2. Hdfs ...
- Python协程中使用上下文
在Python 3.7中,asyncio 协程加入了对上下文的支持.使用上下文就可以在一些场景下隐式地传递变量,比如数据库连接session等,而不需要在所有方法调用显示地传递这些变量.使用得当的话, ...
- 基于STM32F103的Max30100心率、血氧检测代码(转载)
MAX30100是能够读取心率.血氧的传感器,通信方式是通过IIC进行通信.其工作原理是通过红外led灯照射,能够得到心率的ADC值. MAX30100的寄存器可以分为五类,状态寄存器.F ...
- 数据库 MySQL part2
表记录的操作 增 1.插入一条记录 语法:insert [into] tab_name (field1,filed2,.......) values (value1,value2,.......); ...
- RelativeSource设定绑定方向
<Window x:Class="Yingbao.Chapter2.RelativeEx.AppWin" xmlns="http://schemas.microso ...
- 利尔达NB-IOT模块对接移动onenet平台步骤
1. 首先登陆浙江移动onenet网站,http://openiot.zj.chinamobile.com/,进入右上角的开发者中心,然后才能看到创建产品 2. 填写产品的信息,其他信息按照个人实际填 ...
- 转MySQL详解--索引
写在前面:索引对查询的速度有着至关重要的影响,理解索引也是进行数据库性能调优的起点.考虑如下情况,假设数据库中一个表有10^6条记录,DBMS的页面大小为4K,并存储100条记录.如果没有索引,查询将 ...
- .NET基础知识之八——深拷贝,浅拷贝
目录 1.概念 2.使用赋值符号"=" 3.浅复制 4.深复制 5.问题一:如果类里面嵌套有多个类,然后嵌套类里面又嵌套类,那么像上面实现深拷贝的方法还能用吗? 6.问题二:实现深 ...