首先易得方程,且经过变换有

$$\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]购票 「树上斜率优化」的更多相关文章

  1. BZOJ_3672_ [Noi2014]购票_CDQ分治+斜率优化

    BZOJ_3672_ [Noi2014]购票_CDQ分治+斜率优化 Description  今年夏天,NOI在SZ市迎来了她30周岁的生日.来自全国 n 个城市的OIer们都会从各地出发,到SZ市参 ...

  2. 【BZOJ3672】[Noi2014]购票 树分治+斜率优化

    [BZOJ3672][Noi2014]购票 Description  今年夏天,NOI在SZ市迎来了她30周岁的生日.来自全国 n 个城市的OIer们都会从各地出发,到SZ市参加这次盛会.       ...

  3. 【BZOJ-3672】购票 树分治 + 斜率优化DP

    3672: [Noi2014]购票 Time Limit: 30 Sec  Memory Limit: 512 MBSubmit: 1177  Solved: 562[Submit][Status][ ...

  4. [洛谷U22158]策划体验(树上斜率优化)(二分最优决策)

    题目背景 OL不在,Clao又在肝少*前线,他虽然觉得这个游戏的地图很烦,但是他认为地图的难度还是太低了,习习中作为策划还不够FM,于是他自己YY了一种新的地图和新的机制: 题目描述 整个地图呈树形结 ...

  5. UOJ#7. 【NOI2014】购票 点分治 斜率优化 凸包 二分

    原文链接https://www.cnblogs.com/zhouzhendong/p/UOJ7.html 题解 这题是Unknown的弱化版. 如果这个问题出在序列上,那么显然可以CDQ分治 + 斜率 ...

  6. [NOI2007]货币兑换 「CDQ分治实现斜率优化」

    首先每次买卖一定是在某天 $k$ 以当时的最大收入买入,再到第 $i$ 天卖出,那么易得方程: $$f_i = \max \{\frac{A_iRate_kf_k}{A_kRate_k + B_k} ...

  7. [Bzoj1767][Ceoi2009]harbingers (树上斜率优化)

    1767: [Ceoi2009]harbingers Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 451  Solved: 120[Submit][S ...

  8. HDU - 59562016ACM/ICPC亚洲区沈阳站I - The Elder 树上斜率优化dp

    题意:给定上一棵树,然后每条边有一个权值,然后每个点到 1 的距离有两种,第一种是直接回到1,花费是 dist(1, i)^2,还有另一种是先到另一个点 j,然后两从 j 向1走,当然 j 也可以再向 ...

  9. ☆ [洛谷P2633] Count on a tree 「树上主席树」

    题目类型:主席树+\(LCA\) 传送门:>Here< 题意:给出一棵树.每个节点有点权.问某一条路径上排名第\(K\)小的点权是多少 解题思路 类似区间第\(K\)小,但放在了树上. 考 ...

随机推荐

  1. [UVALive 3683] A Scheduling Problem

    图片加载可能有点慢,请跳过题面先看题解,谢谢 题目给出了一个信息:答案是有向边最长路 \(k\) 的值或者是 \(k+1\) 的值 那么题目就变成了:求是否有一种给无向边定向的方案,使得在以有向边最长 ...

  2. 【Cf #299 C】Tavas and Pashmaks(单调栈,凸性)

    一个经典的二维数点模型,如果某个人 $ x $ 两个速度都比另一个人 $ y $ 大,显然 $y$ 是不可能成为winner的. 但这里只考虑两个人$x$,$y$在两个属性各有千秋的时候,一定存在正整 ...

  3. 洛谷 P1199 三国游戏 解题报告

    P1199 三国游戏 题目描述 小涵很喜欢电脑游戏,这些天他正在玩一个叫做<三国>的游戏. 在游戏中,小涵和计算机各执一方,组建各自的军队进行对战.游戏中共有\(N\)位武将(\(N\)为 ...

  4. Java考试题之九

    QUESTION 177 Given: 1.     class TestException extends Exception { } 2.     class A { 3.     public ...

  5. ---web模型 --mvc和模型--struts2 入门

    关于web模型: 早期的web 应用主要是静态页丽的浏览〈如新闻的制监),随着Internet的发展,web应用也变得越来越复杂,不仅要 和数据库进行交互 ,还要和用户进行交互,由此衍生了各种服务器端 ...

  6. 实现运行在独立线程池的调度功能,基于Spring和Annotation

    使用Spring的注解(@Scheduled)声明多个调度的时候,由于其默认实现机制,将导致多个调度方法之间相互干扰(简单理解就是调度不按配置的时间点执行). 为了解决该问题尝试了修改线程池大小,但是 ...

  7. P3866 [TJOI2009]战争游戏

    P3866 [TJOI2009]战争游戏 题目背景 小R正在玩一个战争游戏.游戏地图是一个M行N列的矩阵,每个格子可能是障碍物,也可能是空地,在游戏开始时有若干支敌军分散在不同的空地格子中.每支敌军都 ...

  8. jdk与jdt

    jdk是java的开发环境 ,程序的编译.运行都需要jdk.一个java开发平台,jdk少不了,而编辑器 可以多种多样,除了 eclipse中的JDT,还有独立的jcreate ,或者用记事本以其他加 ...

  9. (转) 经典功率谱估计及Matlab仿真

    原文出自:http://www.cnblogs.com/jacklu/p/5140913.html 功率谱估计在分析平稳各态遍历随机信号频率成分领域被广泛使用,并且已被成功应用到雷达信号处理.故障诊断 ...

  10. android listview使用自定义的adapter没有了OnItemClickListener事件解决办法

    在使用listview的时用使用自定义的adapter的时候,如果你的item布局中包含有Button,Checkable继承来的所有控件,那么你将无法获取listview的onItemClickLi ...