P3994 高速公路 树形DP+斜率优化+二分
$ \color{#0066ff}{ 题目描述 }$
C国拥有一张四通八达的高速公路网树,其中有n个城市,城市之间由一共n-1条高速公路连接。除了首都1号城市,每个城市都有一家本地的客运公司,可以发车前往全国各地,有若干条高速公路连向其他城市,这是一个树型结构,1号城市(首都)为根。假设有一个人要从i号城市坐车出发前往j号城市,那么他要花费Pi*(i城市到j城市的距离)+Qi元。由于距离首都越远,国家的监管就越松,所以距离首都越远,客运公司的Pi(单位距离价格)越大,形式化的说,如果把高速路网看成一棵以首都为根的有根树,i号城市是j号城市的某个祖先,那么一定存在Pi<=Pj。
大宁成为了国家统计局的调查人员,他需要对现在的高速路网进行一次调查,了解从其他每一个城市到达首都1号城市所花费的金钱(路径必须是简单路径)。
因为有非常多转车(或不转车)的抵达首都的方法,所以人工计算这个结果是十分复杂的。大宁非常的懒,所以请你编写一个程序解决它。
\(\color{#0066ff}{输入格式}\)
第 1 行包含1个非负整数 n,表示城市的个数。
第 2 到 n 行,每行描述一个除首都之外的城市。其中第 i 行包含4 个非负整数 Fi,Si,Pi,Qi,分别表示 i号城市的父亲城市,它到父亲城市高速公路的长度,以及乘车价格的两个参数。
\(\color{#0066ff}{输出格式}\)
输出包含 n-1 行,每行包含一个整数。
其中第 i 行表示从 i+1号城市 出发,到达首都最少的乘车费用。
\(\color{#0066ff}{输入样例}\)
6
1 9 3 0
1 17 1 9
1 1 1 6
4 13 2 15
4 9 2 4
\(\color{#0066ff}{输出样例}\)
27
26
7
43
24
\(\color{#0066ff}{数据范围与提示}\)
对于前40%的数据1<=n<=1000。
对于另外20%的数据 满足从第i(i≠1)个城市出发的高速公路连向第i-1个城市。
对于所有的数据1<=n<=1000000,0<=Pi,Qi<=2^31-1,保证结果不会大于2^63-1。
\(\color{#0066ff}{题解}\)
不难想到DP,设\(f[i]\)为从i到根的答案,转移也很好想
\(f[i] =min(f[i],f[j]+(dis[i])-dis[j])*p[i]+q[i])\)
但是这样转移是\(O(n^2)\)的,显然过不了啊
我们考虑斜率优化
如果x比y优秀,即\(f[x]+(dis[i]-dis[x])*p[i]+q[i]<f[y]+(dis[i]-dis[y])*p[i]+q[i]\)
化简之后是\(p[i]<\frac{f[x]-f[y]}{dis[x]-dis[y]}\)
这样就能斜率优化了,用单调队列维护一个下凸包
但是,这是优化的树形DP啊, 在一棵子树内的决策会影响到另一棵子树!
我们考虑每次转移单调队列的变化,看能不能搞点什么
可以发现,每次head仅仅是移动,其中元素是不变的(祖先链不变)
tail呢?每次移动后只会修改一个值!
所以我们可以记录一下每个点的head和tail,还有修改的元素位置和编号,这样就可以快速回溯
但是这样每个点会入队多次,上界依然是\(O(n^2)\)
又因为元素是不变的,所以,我们考虑二分来优化这个过程,每次二分两次,找到转移点和修改点即可
#include<bits/stdc++.h>
#define LL long long
LL in() {char ch; LL x = 0, f = 1;while(!isdigit(ch = getchar()))(ch == '-') && (f = -f);for(x = ch ^ 48; isdigit(ch = getchar()); x = (x << 1) + (x << 3) + (ch ^ 48));return x * f;
}
const int maxn = 1e6 + 100;
LL dep[maxn], f[maxn];
LL p[maxn], q[maxn];
int st[maxn], head, tail;
int n;
struct node {int to, dis;node *nxt;node(int to = 0, int dis = 0, node *nxt = NULL): to(to), dis(dis), nxt(nxt) {}
}*h[maxn];
void add(int from, int to, int dis) { h[from] = new node(to, dis, h[from]); }
void dfs(int x) { for(node *i = h[x]; i; i = i->nxt) dep[i->to] = dep[x] + i->dis, dfs(i->to); }
double K(int x, int y) { return (double)(f[x] - f[y]) / (double)(dep[x] - dep[y]); }
void work(int x) {int nowhead = head, nowtail = tail;int l = head, r = tail - 1, ans = -1;while(l <= r) {int mid = (l + r) >> 1;if(p[x] <= K(st[mid], st[mid + 1])) ans = mid, r = mid - 1;else l = mid + 1;}if(~ans) head = ans;else head = tail;f[x] = f[st[head]] + (dep[x] - dep[st[head]]) * p[x] + q[x];l = head, r = tail - 1, ans = -1;while(l <= r) {int mid = (l + r) >> 1;if(K(st[mid], st[mid + 1]) < K(st[mid + 1], x)) ans = mid, l = mid + 1;else r = mid - 1;}if(~ans) tail = ans + 1;else tail = head;int now = st[++tail];st[tail] = x;for(node *i = h[x]; i; i = i->nxt) work(i->to);head = nowhead, st[tail] = now, tail = nowtail;
}
int main() {n = in();int x, y;for(int i = 2; i <= n; i++) {x = in(), y = in();add(x, i, y);p[i] = in(), q[i] = in();}dfs(1);for(node *i = h[1]; i; i = i->nxt) st[head = tail = 1] = 1, work(i->to);for(int i = 2; i <= n; i++) printf("%lld\n", f[i]);return 0;
}
转载于:https://www.cnblogs.com/olinr/p/10532737.html
P3994 高速公路 树形DP+斜率优化+二分相关推荐
- 【bzoj2500】幸福的道路 树形dp+倍增RMQ+二分
原文地址:http://www.cnblogs.com/GXZlegend/p/6825389.html 题目描述 小T与小L终于决定走在一起,他们不想浪费在一起的每一分每一秒,所以他们决定每天早上一 ...
- bzoj1492 货币兑换cash dp斜率优化+splay/cdq分治
斜率优化 首先,由于如果在i天买在j天卖有利可图,那么最优方法就是在i天花完钱在j天卖完.我们令 f i f_i fi为第i天可以得到的最多钱数,然后可以先列方程求出花完钱在第j天得到的两种金券数 ...
- BZOJ 1597: [Usaco2008 Mar]土地购买( dp + 斜率优化 )
既然每块都要买, 那么一块土地被另一块包含就可以不考虑. 先按长排序, 去掉不考虑的土地, 剩下的土地长x递增, 宽y递减 dp(v) = min{ dp(p)+xv*yp+1 } 假设dp(v)由i ...
- BZOJ 3156: 防御准备( dp + 斜率优化 )
dp(i)表示处理完[i,n]且i是放守卫塔的最小费用. dp(i) = min{dp(j) + (j-i)(j-i-1)/2}+costi(i<j≤N) 然后斜率优化 ------------ ...
- 【BZOJ-3156】防御准备 DP + 斜率优化
3156: 防御准备 Time Limit: 10 Sec Memory Limit: 512 MB Submit: 951 Solved: 446 [Submit][Status][Discus ...
- [HNOI2008]玩具装箱toy(dp+斜率优化)
斜率优化问题一般都是决策单调问题.对于这题能够证明单调决策. 令sum[i]=sigma(c [k] ) 1<=k<=i , f[i]=sum[i]+i , c=L+1; 首先我们能 ...
- UVAlive 6131 dp+斜率优化
这道题和06年论文<从一类单调性问题看算法的优化>第一道例题很相似. 题意:给出n个矿的重量和位置,这些矿石只能从上往下运送,现在要在这些地方建造m个heap,要使得,sigma距离*重量 ...
- hdu 3507 Print Article(dp+斜率优化)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3507 题解:显然这题的递推很容易得到 dp[i]=dp[j]+(sum[i]-sum[j])^2+m ...
- C++剑指offer:解题报告之DP优化学习记 (二) ——浅论DP斜率优化 (Print Article 【HDU - 3507】 )
链接:https://share.weiyun.com/5LzbzAc 目录 前言 斜率优化前期准备 1.从状态转移方程出发 2.推理状态转移方程 对结论的进一步推导 干货!综合结论 判断斜率大小的方 ...
最新文章
- AI算力需求6年增长30万倍,「超异构计算」才能满足下一个10年
- 网络层IP路由的负载均衡实现思路
- 在WebView中如何让JS与Java安全地互相调用
- XCTF-MISC-新手区:give_you_flag
- Flutter-现有iOS工程引入Flutter
- 惨痛教训,事实证明ACER 4710无法使用双芯片的内置蓝牙
- 《Redis+Nginx+设计模式+Spring全家桶+Dubbo》,附 PDF amp; 简历模板 下载
- mysql查看执行计划任务_学习计划 mysql explain执行计划任务详解
- mp4 box linux,MP4Box
- 数据分析/挖掘的六个步骤
- 《康熙王朝》剧情分集介绍【全】
- Win10 - 卸载自带应用
- oscp——five86-1
- 标准椭圆和任意椭圆方程之间的变换公式推导
- Kronecker克罗内克 R代码实现
- Shadowing, Overriding, Hiding and Obscuring
- 美国大学本科计算机本科排名,2017美国大学计算机排名本科
- JAVA大数据的第五十九天——The authenticity of host ‘gree129 (192.168.**.129)‘ can‘t be established.
- ad禁用计算机账户命令,AD-禁用账户命令 Disable-ADAccount
- 【Elasticsearch系列】文档的基本操作
热门文章
- [ANOJ]1022库洛值[字符串处理].cpp
- 【渗透测试框架】Metasploit-Framework(MSF)安装与使用
- 算法竞赛入门经典_键盘字符输入问题C++实现
- 饿了么 python_饿了么深度学习平台 elearn
- linux 读取u盘数据恢复,Linux 数据恢复
- Flowable进阶学习(五)候选人与候选人组
- 【TypeScript】深入学习TypeScript对象类型
- 手机移动端审批安装教程
- 成都翰麟教育|中学教师资格复习方法总结
- 【Python】实现指定数组下标值正序和倒序排序算法功能