[NOI2014]购票 「树上斜率优化」
首先易得方程,且经过变换有
$$\begin{aligned} f_i &= \min\limits_{dist_i - lim_i \le dist_j} \{f_j + (dist_i - dist_j)p_i + q_i\} \\ f_j &= p_idist_j + f_i - dist_ip_i - q_i \end{aligned}$$
在一条直线上时,斜率优化可以用普通$CDQ$分治实现(会不会过于麻烦?),那么对于在树上斜率优化时,考虑点分治
这时就在点分治中运用$CDQ$分治的思想,即使用在当前重心管辖范围内的通向根节点的那一条链上的节点来更新其它节点就好了
注意在分治中的斜率优化时在凸包上加点和更新右侧节点答案要同时进行,不然当前最优解可能会在后面由于斜率被删去,导致答案错误,还有由于下面代码是由深度由小到大处理的,所以是反着维护下凸包,即上凸包
代码
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath> using namespace std; typedef long long LL; const int MAXN = 2e05 + ;
const int MAXM = 2e05 + ; const int INF = 0x7fffffff;
const LL INFLL = 0x3f3f3f3f3f3f3f3f;
const double eps = 1e-; int Dcmp (double p) {
if (fabs (p) < eps)
return ;
return p < ? - : ;
} struct LinkedForwardStar {
int to; int next;
} ; LinkedForwardStar Link[MAXM << ];
int Head[MAXN]= {};
int size = ; void Insert (int u, int v) {
Link[++ size].to = v;
Link[size].next = Head[u]; Head[u] = size;
} const int Root = ; struct CitySt {
LL p, q, lim; CitySt () {}
} ;
CitySt City[MAXN]; LL f[MAXN]; int N;
LL Fdist[MAXN]= {}; LL Dist[MAXN]= {};
int Father[MAXN]= {};
void DFS (int root, int father) {
for (int i = Head[root]; i; i = Link[i].next) {
int v = Link[i].to;
if (v == father)
continue;
Dist[v] = Dist[root] + Fdist[v];
DFS (v, root);
}
} int Vis[MAXN]= {}; int Size[MAXN]= {};
int grvy, minval = INF;
int total;
void Grvy_Acqu (int root, int father) {
Size[root] = ;
int maxpart = ;
for (int i = Head[root]; i; i = Link[i].next) {
int v = Link[i].to;
if (v == father || Vis[v])
continue;
Grvy_Acqu (v, root);
Size[root] += Size[v];
maxpart = max (maxpart, Size[v]);
}
maxpart = max (maxpart, total - Size[root]);
if (maxpart < minval)
grvy = root, minval = maxpart;
} int temp[MAXN];
int p = ;
int Que[MAXN];
double slope (int a, int b) {
if (Dist[a] == Dist[b])
return INFLL * 1.0;
return (double) (f[b] - f[a]) * 1.0 / (double) (Dist[b] - Dist[a]) * 1.0;
}
int listq[MAXN];
int lp = ;
bool comp (const int& a, const int& b) {
return Dist[a] - City[a].lim > Dist[b] - City[b].lim;
}
void listq_Acqu (int root, int father) {
if (father)
listq[++ lp] = root;
for (int i = Head[root]; i; i = Link[i].next) {
int v = Link[i].to;
if (v == father || Vis[v])
continue;
listq_Acqu (v, root);
}
}
int Binary_Search (int left, int right, int p) {
if (left == right)
return left;
int l = left, r = right;
while (l < r) {
int mid = (l + r) >> ;
if (f[Que[mid + ]] - f[Que[mid]] <= p * (Dist[Que[mid + ]] - Dist[Que[mid]]))
l = mid + ;
else
r = mid;
}
return l;
}
void Update (int left, int right, int tp) {
if (left > right)
return ;
int p = Binary_Search (left, right, City[tp].p);
f[tp] = min (f[tp], f[Que[p]] + (Dist[tp] - Dist[Que[p]]) * City[tp].p + City[tp].q);
}
void Solve (int root) {
minval = INF, total = Size[root], Grvy_Acqu (root, );
Vis[grvy] = true;
int fgrvy = grvy;
if (grvy != root) {
Size[root] -= Size[grvy];
Solve (root);
}
p = ;
temp[++ p] = fgrvy;
for (int nd = fgrvy; nd != root; nd = Father[nd]) {
if (Dist[fgrvy] - City[fgrvy].lim <= Dist[Father[nd]])
f[fgrvy] = min (f[fgrvy], f[Father[nd]] + (Dist[fgrvy] - Dist[Father[nd]]) * City[fgrvy].p + City[fgrvy].q);
temp[++ p] = Father[nd];
}
lp = ;
listq_Acqu (fgrvy, );
sort (listq + , listq + lp + , comp);
int left = , right = ;
int j = ;
for (int i = ; i <= p && j <= lp; i ++) { // 斜率优化
while (j <= lp && Dist[temp[i]] < Dist[listq[j]] - City[listq[j]].lim)
Update (left, right, listq[j ++]);
while (left < right && Dcmp (slope (Que[right - ], Que[right]) - slope (Que[right], temp[i])) <= ) // 注意是上凸包
right --;
Que[++ right] = temp[i];
}
while (j <= lp)
Update (left, right, listq[j ++]);
for (int i = Head[fgrvy]; i; i = Link[i].next) {
int v = Link[i].to;
if (Vis[v])
continue;
Solve (v);
}
} int getint () {
int num = ;
char ch = getchar (); while (! isdigit (ch))
ch = getchar ();
while (isdigit (ch))
num = (num << ) + (num << ) + ch - '', ch = getchar (); return num;
} LL getLL () {
LL num = ;
char ch = getchar (); while (! isdigit (ch))
ch = getchar ();
while (isdigit (ch))
num = (num << ) + (num << ) + ch - '', ch = getchar (); return num;
} int main () {
// freopen ("Input.txt", "r", stdin);
// freopen ("Output.txt", "w", stdout); memset (f, 0x3f3f3f3f, sizeof (f));
f[Root] = ;
N = getint (), getint ();
for (int i = ; i <= N; i ++) {
int fa = getint ();
Father[i] = fa;
Fdist[i] = getLL ();
City[i].p = getLL (), City[i].q = getLL (), City[i].lim = getLL ();
Insert (fa, i), Insert (i, fa);
}
DFS (Root, );
Size[Root] = N;
Solve (Root);
for (int i = ; i <= N; i ++)
printf ("%lld\n", f[i]); return ;
} /*
7 3
1 2 20 0 3
1 5 10 100 5
2 4 10 10 10
2 9 1 100 10
3 5 20 100 10
4 4 20 0 10
*/
[NOI2014]购票 「树上斜率优化」的更多相关文章
- BZOJ_3672_ [Noi2014]购票_CDQ分治+斜率优化
BZOJ_3672_ [Noi2014]购票_CDQ分治+斜率优化 Description 今年夏天,NOI在SZ市迎来了她30周岁的生日.来自全国 n 个城市的OIer们都会从各地出发,到SZ市参 ...
- 【BZOJ3672】[Noi2014]购票 树分治+斜率优化
[BZOJ3672][Noi2014]购票 Description 今年夏天,NOI在SZ市迎来了她30周岁的生日.来自全国 n 个城市的OIer们都会从各地出发,到SZ市参加这次盛会. ...
- 【BZOJ-3672】购票 树分治 + 斜率优化DP
3672: [Noi2014]购票 Time Limit: 30 Sec Memory Limit: 512 MBSubmit: 1177 Solved: 562[Submit][Status][ ...
- [洛谷U22158]策划体验(树上斜率优化)(二分最优决策)
题目背景 OL不在,Clao又在肝少*前线,他虽然觉得这个游戏的地图很烦,但是他认为地图的难度还是太低了,习习中作为策划还不够FM,于是他自己YY了一种新的地图和新的机制: 题目描述 整个地图呈树形结 ...
- UOJ#7. 【NOI2014】购票 点分治 斜率优化 凸包 二分
原文链接https://www.cnblogs.com/zhouzhendong/p/UOJ7.html 题解 这题是Unknown的弱化版. 如果这个问题出在序列上,那么显然可以CDQ分治 + 斜率 ...
- [NOI2007]货币兑换 「CDQ分治实现斜率优化」
首先每次买卖一定是在某天 $k$ 以当时的最大收入买入,再到第 $i$ 天卖出,那么易得方程: $$f_i = \max \{\frac{A_iRate_kf_k}{A_kRate_k + B_k} ...
- [Bzoj1767][Ceoi2009]harbingers (树上斜率优化)
1767: [Ceoi2009]harbingers Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 451 Solved: 120[Submit][S ...
- HDU - 59562016ACM/ICPC亚洲区沈阳站I - The Elder 树上斜率优化dp
题意:给定上一棵树,然后每条边有一个权值,然后每个点到 1 的距离有两种,第一种是直接回到1,花费是 dist(1, i)^2,还有另一种是先到另一个点 j,然后两从 j 向1走,当然 j 也可以再向 ...
- ☆ [洛谷P2633] Count on a tree 「树上主席树」
题目类型:主席树+\(LCA\) 传送门:>Here< 题意:给出一棵树.每个节点有点权.问某一条路径上排名第\(K\)小的点权是多少 解题思路 类似区间第\(K\)小,但放在了树上. 考 ...
随机推荐
- 怎么解决Xing欲
怎么解决Xing欲 来源:微信号 王路在隐身 这是知乎上的一道问题.原题叫<和尚怎么解决性欲>. 本来由出家人回答更合适,但估计出家人一般不太愿意回答. 我看了几十个答案,几乎都是在调侃出 ...
- 【bzoj2594】 Wc2006—水管局长数据加强版
http://www.lydsy.com/JudgeOnline/problem.php?id=2594 (题目链接) 题意 给出一个带边权的无向简单,要求维护两个操作,删除${u,v}$之间的连边: ...
- wazuh安装手册
一.wazhu部署架构 1.服务器上运行的Agent端会将采集到的各种信息通过加密信道传输到管理端. 2.管理端负责分析从代理接收的数据,并在事件与告警规则匹配时触发警报. 3.LogStash会将告 ...
- 【arc073D】Many Moves
Portal -->arc073D Description 有\(n\)个格子,编号从左到右为\(1\sim n\),一开始有两个棋子,位置给定,接下来要依次进行\(Q\)次操作,第\(i\ ...
- JavaScript匿名函数知多少
在一些Javascript库中可以看见这种写法: function(){ //所有库代码代码 }(); 这样写的一个目的是——封装. JavaScript并不是面向对象的,所以它不支持封装.但是在不支 ...
- JavaScript演示下Singleton设计模式
单例模式的基本结构: MyNamespace.Singleton = function() { return {}; }(); 比如: MyNamespace.Singleton = (functio ...
- webpack 多页面|入口支持和公共组件单独打包--转载
转载自:http://www.jb51.net/article/117490.htm 本篇主要介绍:如何自动构建入口文件,并生成对应的output:公共js库如何单独打包. 多入口文件,自动扫描入口. ...
- Linux QT数据库之登录注册
视频链接:https://www.bilibili.com/video/av11673511/ main.cpp #include <QSqlDatabase> #include < ...
- UIKit类图
- 如何给list清空
1.list = new ArrayList<String>(): 2.list.clear(); 3.list=null;