洛谷P3994 Highway(树形DP+斜率优化+可持久化线段树/二分)
有点类似NOI2014购票
首先有方程$f(i)=min\{f(j)+(dep_i-dep_j)*p_i+q_i\}$
这个显然是可以斜率优化的...
$\frac {f(j)-f(k)}{dep_j-dep_k}<p_i$
$p_i$是单调的,于是可以单调队列,当遍历完一个子树的时候,必须复原单调队列到进入这棵子树前的样子,这个用可持久化线段树维护可持久化数组显然可做...
当然有更聪明的方法。
单调队列队头出去的时候实际上队列信息不会被覆盖,于是恢复左端点只要记录进入当前点前的左端点即可。
右端点可能会被覆盖,但是每次最多覆盖一个点(也就是当前点),于是恢复右端点只需要记录进入当前点前的右端点和被覆盖的值即可。
但是这么做的话无法保证一个点出队入队次数是常数级别的,也就无法保证复杂度是$O(n)$了,所以每次不能一个一个出队(一条链加一朵大菊花就可以卡了),必须二分出队位置,才可以保证复杂度,做到$O(nlogn)$。
但是出题人没有卡暴力出队的做法...我写二分比直接暴力弹出跑得快= =... 事实证明是评测机玄学...有时候跑得快有时候跑得慢
二分:
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#define ll long long
using namespace std;
const int maxn=, inf=1e9;
struct poi{int too, dis, pre;}e[maxn];
int n, x, z, tot, l, r;
int p[maxn], Q[maxn], last[maxn], nowl[maxn], nowr[maxn], nowqr[maxn], q[maxn];
ll f[maxn], d[maxn];
inline void read(int &k)
{
int f=; k=; char c=getchar();
while(c<'' || c>'') c=='-' && (f=-), c=getchar();
while(c<='' && c>='') k=k*+c-'', c=getchar();
k*=f;
}
inline void add(int x, int y, int z){e[++tot]=(poi){y, z, last[x]}; last[x]=tot;}
inline double xl(int j, int k){return 1.0*(f[j]-f[k])/(d[j]-d[k]);}
inline void dfs(int x)
{
nowl[x]=l;
if(l<r)
{
int L=l, R=r-;
while(L<R)
{
int mid=(L+R)>>;
if(p[x]-xl(q[mid+], q[mid])>1e-) L=mid+;
else R=mid;
}
l=(p[x]-xl(q[L], q[L+])>1e-)?L+:L;
}
nowr[x]=r;
if(x!=) f[x]=f[q[l]]+Q[x]+1ll*(d[x]-d[q[l]])*p[x];
if(l<r)
{
int L=l+, R=r;
while(L<R)
{
int mid=(L+R+)>>;
if(xl(x, q[mid])<xl(q[mid], q[mid-])) R=mid-;
else L=mid;
}
r=(xl(x, q[L])<xl(q[L-], q[L]))?L-:L;
}
nowqr[x]=q[r+]; q[++r]=x;
for(int i=last[x], too;i;i=e[i].pre) d[too=e[i].too]=d[x]+e[i].dis, dfs(too);
l=nowl[x]; q[r]=nowqr[x]; r=nowr[x];
}
int main()
{
read(n);
for(int i=;i<=n;i++) read(x), read(z), add(x, i, z), read(p[i]), read(Q[i]);
l=; r=; dfs();
for(int i=;i<=n;i++) printf("%lld\n", f[i]);
}
暴力出队:
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#define ll long long
using namespace std;
const int maxn=, inf=1e9;
struct poi{int too, dis, pre;}e[maxn];
int n, x, z, tot, l, r;
int p[maxn], Q[maxn], last[maxn], nowl[maxn], nowr[maxn], nowqr[maxn], q[maxn];
ll f[maxn], d[maxn];
inline void read(int &k)
{
int f=; k=; char c=getchar();
while(c<'' || c>'') c=='-' && (f=-), c=getchar();
while(c<='' && c>='') k=k*+c-'', c=getchar();
k*=f;
}
inline void add(int x, int y, int z){e[++tot]=(poi){y, z, last[x]}; last[x]=tot;}
inline double xl(int j, int k){return 1.0*(f[j]-f[k])/(d[j]-d[k]);}
inline void dfs(int x)
{
nowl[x]=l; while(l<r && p[x]-xl(q[l+], q[l])>1e-) l++;
if(x!=) f[x]=f[q[l]]+Q[x]+1ll*(d[x]-d[q[l]])*p[x];
nowr[x]=r; while(l<r && xl(x, q[r])<xl(q[r], q[r-])) r--;
nowqr[x]=q[r+]; q[++r]=x;
for(int i=last[x], too;i;i=e[i].pre) d[too=e[i].too]=d[x]+e[i].dis, dfs(too);
l=nowl[x]; q[r]=nowqr[x]; r=nowr[x];
}
int main()
{
read(n);
for(int i=;i<=n;i++) read(x), read(z), add(x, i, z), read(p[i]), read(Q[i]);
l=; r=; dfs();
for(int i=;i<=n;i++) printf("%lld\n", f[i]);
}
洛谷P3994 Highway(树形DP+斜率优化+可持久化线段树/二分)的更多相关文章
- P3994 高速公路 树形DP+斜率优化+二分
$ \color{#0066ff}{ 题目描述 }$ C国拥有一张四通八达的高速公路网树,其中有n个城市,城市之间由一共n-1条高速公路连接.除了首都1号城市,每个城市都有一家本地的客运公司,可以发车 ...
- 洛谷P4027 [NOI2007]货币兑换(dp 斜率优化 cdq 二分)
题意 题目链接 Sol 解题的关键是看到题目里的提示... 设\(f[i]\)表示到第\(i\)天所持有软妹币的最大数量,显然答案为\(max_{i = 1}^n f[i]\) 转移为\(f_i = ...
- bzoj3672: [Noi2014]购票(树形DP+斜率优化+可持久化凸包)
这题的加强版,多了一个$l_i$的限制,少了一个$p_i$的单调性,难了好多... 首先有方程$f(i)=min\{f(j)+(dep_i-dep_j)*p_i+q_i\}$ $\frac {f(j) ...
- 洛谷P2365 任务安排(斜率优化dp)
传送门 思路: 最朴素的dp式子很好考虑:设\(dp(i,j)\)表示前\(i\)个任务,共\(j\)批的最小代价. 那么转移方程就有: \[ dp(i,j)=min\{dp(k,j-1)+(sumT ...
- 洛谷P2120 [ZJOI2007]仓库建设 斜率优化DP
做的第一道斜率优化\(DP\)QwQ 原题链接1/原题链接2 首先考虑\(O(n^2)\)的做法:设\(f[i]\)表示在\(i\)处建仓库的最小费用,则有转移方程: \(f[i]=min\{f[j] ...
- 洛谷4072 SDOI2016征途 (斜率优化+dp)
首先根据题目中给的要求,推一下方差的柿子. \[v\times m^2 = m\times \sum x^2 - 2 \times sum \times sum +sum*sum \] 所以\(ans ...
- Codeforces 1179D 树形DP 斜率优化
题意:给你一颗树,你可以在树上添加一条边,问添加一条边之后的简单路径最多有多少条?简单路径是指路径中的点只没有重复. 思路:添加一条边之后,树变成了基环树.容易发现,以基环上的点为根的子树的点中的简单 ...
- 洛谷P4072 [SDOI2016]征途(斜率优化)
传送门 推式子(快哭了……)$$s^2*m^2=\sum _{i=1}^m (x_i-\bar{x})^2$$ $$s^2*m^2=m*\sum _{i=1}^m x_i^2-2*sum_n\sum ...
- 洛谷3571 POI2014 SUP-Supercomputer (斜率优化)
一道神仙好题. 首先看到有多组\(k\),第一反应就是离线. 考虑贪心. 我们每次一定是尽量选择有儿子的节点.以便于我们下一次扩展. 但是对于一个\(k\),每次贪心的复杂度是\(O(n)\) 总复杂 ...
随机推荐
- ats 转发代理
ats是一个通用代理,可配置为反向和转发代理; 转发代理可以用作基础架构中的中央工具来访问web, 它可以与缓存结合使用以降低 总体带宽使用率.转发代理充当本地网络上的客户端浏览器与这些客户端访问的所 ...
- Streamr助你掌控自己的数据(1)——教你5分钟上传数据至Streamr
博客说明 所有刊发内容均可转载但是需要注明出处. 教你5分钟上传数据至Streamr 本系列文档主要介绍怎么通过Streamr管理自己的DATA,整个系列包括三篇教程文档,分别是:教你5分钟上传数据至 ...
- [朴孝敏][Road Trip]
歌词来源:http://music.163.com/#/song?id=406907305 作曲 : Ryan S. Jhun/G'harah 'PK' Degeddingseze/Denzil Re ...
- 部署Maven项目到tomcat报错:java.lang.ClassNotFoundException: org.springframework.web.context.ContextLoaderListener【转】
部署Maven项目到tomcat报错:java.lang.ClassNotFoundException: org.springframework.web.context.ContextLoaderLi ...
- vim 多个文件切换 :b 命令
MiniBufExplorer插件的使用 博客分类: vim vimMiniBufExplorer 快速浏览和操作Buffer -- 插件: MiniBufExplorer 下载地址 [http:// ...
- teamwork 2
1.访问上学期项目团队,学习他们的得失. 上学期学长们有一个项目是学霸系统,在看过了学长们的相关博客后,我们可以感受到学长们确实花费了不少心思,也看到了许多值得我们学习的地方. 首先,学长们在项目开始 ...
- Oracle安装后出现的问题
安装oracle没有勾选"安装模板数据库",可以通过执行以下命令进行修改: cd $ORACLE_HOME/rdbms/admin 到这个目录下sqlplus /as sysdba ...
- Leetcode题库——31.下一个排列
@author: ZZQ @software: PyCharm @file: nextPermutation.py @time: 2018/11/12 15:32 要求: 实现获取下一个排列的函数,算 ...
- wcf服务查看工具
文章:接口测试工具soapUI(一) 文章:VS自带WCF测试客户端简单介绍
- 学习jenv
背景 生活不只是眼前的苟且, 还有诗和远方. 上个月工作需要启动了一个小项目, 按最初的计划会用JDK8. 但当计划报上去后, 运维部门出于后续升级维护的考虑, 不允许使用已经出来4年多的JDK8了, ...