BZOJ3672 [Noi2014]购票 【点分治 + 斜率优化】
题目链接
题解
如果暂时不管\(l[i]\)的限制,并假使这是一条链
设\(f[i]\)表示\(i\)节点的最优答案,我们容易得到\(dp\)方程
\]
显而易见可以斜率优化
化为
\]
那么决策点就是\((d[j],f[j])\),决策就是用斜率为\(p[i]\)的直线截得最小截距
显然维护下凸包即可,而且\(d[j]\)单调,可以逐点加入
好了以上就是直线上不带\(l[i]\)限制的口胡
如果强行搬到树上来,可以使用可持久化数组维护
但是加上\(l[i]\)的限制,仍然强行截出\(l[i]\)之后的点,是不对的
如图:

图中紫色点在过程中被出栈了,截掉\(l[i]\)之前的点之后,并不会在凸包中,而实际应被考虑进来
所以就要使用点分治 + 斜率优化的黑科技了OvO
1、我们先分治一棵以\(u\)为根子树,如果子树大小为\(1\)直接返回
2、寻找到这棵树的重心,先将重心\(rt\)的儿子打个标记堵上
3、然后再分治以\(u\)为根的子树
4、分治完后,显然\(rt\)节点及以上的节点的\(f[i]\)都更新完毕,我们使用\(u\)到\(rt\)路径上所有点来更新子树内的\(f[i]\)
5、将\(rt\)子树内的点拿出来,按\(d[i] - l[i]\)——即最高能对其进行更新的位置——降序排序
6、将\(rt\)及以上节点逐一在可以进行更新时加入凸包,子树内的点在凸包上二分更新答案
7、分治各个子树
树分治是\(O(nlogn)\)的,分治过程中子树内每一个节点都要进行一次二分,所以总复杂度是\(O(nlog^2n)\)
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<map>
#define Redge(u) for (int k = h[u],to; k; k = ed[k].nxt)
#define REP(i,n) for (int i = 1; i <= (n); i++)
#define mp(a,b) make_pair<int,int>(a,b)
#define cls(s) memset(s,0,sizeof(s))
#define cp pair<int,int>
#define LL long long int
using namespace std;
const int maxn = 200005,maxm = 10000005,oo = 1000000000;
const LL INF = 1000000000ll * 1000000001ll;
inline LL read(){
LL out = 0,flag = 1; char c = getchar();
while (c < 48 || c > 57){if (c == '-') flag = -1; c = getchar();}
while (c >= 48 && c <= 57){out = (out << 3) + (out << 1) + c - 48; c = getchar();}
return out * flag;
}
int n,fa[maxn],Ls[maxn],Rb[maxn];
LL p[maxn],q[maxn],f[maxn],L[maxn],d[maxn],s[maxn];
int F[maxn],sz[maxn],rt,vis[maxn];
void getrt(int u,int Siz){
sz[u] = 1; F[u] = 0;
for (int k = Ls[u]; k; k = Rb[k])
if (!vis[k]){
getrt(k,Siz); sz[u] += sz[k]; F[u] = max(F[u],sz[k]);
}
F[u] = max(F[u],Siz - sz[u]);
if (F[u] <= F[rt]) rt = u;
}
int c[maxn],ci;
void dfs(int u){
c[++ci] = u;
for (int k = Ls[u]; k; k = Rb[k]) if (!vis[k]) dfs(k);
}
inline bool cmp(const int& a,const int& b){
return d[a] - L[a] > d[b] - L[b];
}
int st[maxn],top;
double sl[maxn];
double slope(int u,int v){
return (double)(f[u] - f[v]) / (double)(d[u] - d[v]);
}
void ins(int u){
while (top > 1 && slope(u,st[top]) >= sl[top - 1])
top--;
st[++top] = u;
if (top > 1) sl[top - 1] = slope(st[top],st[top - 1]);
sl[top] = -INF;
}
LL query(int u){
int l = 1,r = top,mid;
while (l < r){
mid = l + r>> 1;
if (sl[mid] <= p[u]) r = mid;
else l = mid + 1;
}
return f[st[l]] + (d[u] - d[st[l]]) * p[u] + q[u];
}
void solve(int u,int Siz){
if (Siz == 1) return;
F[rt = 0] = oo; getrt(u,Siz); int x = rt;
for (int k = Ls[x]; k; k = Rb[k]) vis[k] = true,Siz -= sz[k];
solve(u,Siz);
ci = 0; for (int k = Ls[x]; k; k = Rb[k]) dfs(k);
sort(c + 1,c + 1 + ci,cmp);
int now = x; top = 0;
for (int i = 1; i <= ci; i++){
int v = c[i];
while (now != fa[u] && d[v] - L[v] <= d[now]) ins(now),now = fa[now];
if (top) f[v] = min(f[v],query(v));
}
for (int k = Ls[x]; k; k = Rb[k]) solve(k,sz[k]);
}
int main(){
n = read(); read();
for (int i = 2; i <= n; i++){
fa[i] = read(); s[i] = read(); d[i] = d[fa[i]] + s[i];
p[i] = read(); q[i] = read(); L[i] = read();
Rb[i] = Ls[fa[i]]; Ls[fa[i]] = i;
f[i] = INF;
}
solve(1,n);
for (int i = 2; i <= n; i++) printf("%lld\n",f[i]);
return 0;
}
BZOJ3672 [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][ ...
- UOJ#7. 【NOI2014】购票 点分治 斜率优化 凸包 二分
原文链接https://www.cnblogs.com/zhouzhendong/p/UOJ7.html 题解 这题是Unknown的弱化版. 如果这个问题出在序列上,那么显然可以CDQ分治 + 斜率 ...
- [NOI2014]购票 「树上斜率优化」
首先易得方程,且经过变换有 $$\begin{aligned} f_i &= \min\limits_{dist_i - lim_i \le dist_j} \{f_j + (dist_i - ...
- BZOJ3672: [Noi2014]购票(CDQ分治,点分治)
Description 今年夏天,NOI在SZ市迎来了她30周岁的生日.来自全国 n 个城市的OIer们都会从各地出发,到SZ市参加这次盛会. 全国的城市构成了一棵以SZ市为根的有根树 ...
- bzoj千题计划251:bzoj3672: [Noi2014]购票
http://www.lydsy.com/JudgeOnline/problem.php?id=3672 法一:线段树维护可持久化单调队列维护凸包 斜率优化DP 设dp[i] 表示i号点到根节点的最少 ...
- 【uoj#244】[UER #7]短路 CDQ分治+斜率优化dp
题目描述 给出 $(2n+1)\times (2n+1)$ 个点,点 $(i,j)$ 的权值为 $a[max(|i-n-1|,|j-n-1|)]$ ,找一条从 $(1,1)$ 走到 $(2n+1,2n ...
- BZOJ_1492_[NOI2007]货币兑换Cash_CDQ分治+斜率优化
BZOJ_1492_[NOI2007]货币兑换Cash_CDQ分治+斜率优化 Description 小Y最近在一家金券交易所工作.该金券交易所只发行交易两种金券:A纪念券(以下简称A券)和 B纪念券 ...
随机推荐
- 使用TCP在同一台电脑上可以建立连接,在两台电脑上却连接失败的原因分析
最近在用unity做联机游戏,在网络方面费了不少劲,总是在代码没问题的时候出一些莫名奇妙的BUG,不过后来都决定了.如果感觉代码没问题,八成就是防火墙的问题. 用unity发布后的游戏,如果涉及网络, ...
- 关于IPointerEnterHandler和IpointerExitHandler的简单说明
自己在学习UGUI背包系统时用到了,而且遇到一些问题,所以在这里写一下这两个接口的简单说明. 继承IPointerEnterHandler和IpointerExitHandler这两个接口后可以实现两 ...
- C#_Switch语句的内部实现
Switch的C#内部实现 https://www.cnblogs.com/Interkey/p/3730432.html 在IL汇编语言中的Switch指令 -- 按照标号来进行跳转(和goto语句 ...
- [转载]MySQL面试题
1.MySQL的复制原理以及流程基本原理流程,3个线程以及之间的关联:(1)主:binlog线程——记录下所有改变了数据库数据的语句,放进master上的binlog中:(2)从:io线程——在使用s ...
- 互联网校招面试必备——Java多线程
本文首发于我的个人博客:尾尾部落 本文是我刷了几十篇一线互联网校招java后端开发岗位的面经后总结的多线程相关题目,虽然有点小长,但是面试前看一看,相信能帮你轻松啃下多线程这块大骨头. 什么是进程,什 ...
- Table 组件构建过程中遇到的问题与解决思路
在 GearCase 开源项目构建 Table 组件的过程中.遇到了各式各样的问题,最后尝试了各种方法去解决这些问题. 遇到的部分问题 checkbox 的全选和半选问题 table 组件的排序请求方 ...
- 如何防范和应对Redis勒索,腾讯云教你出招
欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 本文由腾讯云数据库 TencentDB发表于云+社区专栏 9月10日下午,又一起规模化利用Redis未授权访问漏洞攻击数据库的事件发生,此次 ...
- Django_WSGIRequest对象
WSGIRequest对象 Django在接收到http请求之后,会根据http请求携带的参数以及报文信息创建一个WSGIRequest对象,并且作为视图函数第一个参数传给视图函数.这个参数就是dja ...
- Spring MVC controller的方法返回值
ModeAndView 可以在构造时确定需要跳转的页面也可以通过setViewName方法来确定需要跳转的页面 String 指定返回页面的视图名称,页面跳转,如果加了@ResponseBody注解, ...
- 第二阶段每日站立会议Second Day
昨天我在手机端安装cpp后进行界面效果测试以及进一步完善 今天对图片显示的大小进行调整 遇到的问题:当图片太小时,显示一块灰色区域,不美观