题解 [NOI2014]购票
题目大意
有一个 \(n\) 个点的树,每个点有三个值 \(p_u,q_u,l_u\) ,现在可以从 \(u\) 走到点 \(v\) 当且仅当 \(v\) 是 \(u\) 的祖先并且 \(\text{dis}(u,v)\le l_u\) ,这样的花费为 \(\text{dis}(u,v)\times p_u+q_u\) 。问每个点到 \(1\) 所需的最小总花费。
\(n\le 2\times 10^5\) ,保证答案在 \(\text{long long}\) 范围内。
思路
还说还是看到 \(\text{Qiuly}\) 做这道题才做的,想要练习一下自己本来就菜的一批的斜率优化,结果发现自己除了斜率优化啥也不会了。。。
我们假设 \(f_u\) 为点 \(u\) 的答案,可以得到转移式:
\]
\]
然后我们就发现这个式子可以斜率优化了。假设对于点 \(u\) 存在点 \(j\) 比点 \(k\) 更优,可以得到:
\]
\]
然后我们发现这个东西我们可以维护一个下凸壳,但是因为 \(p_i\) 并不单调,所以我们直接在凸壳上面二分找到第一个斜率不大于 \(p_i\) 的点就好了。
但是我们发现我们这个东西其实是一棵树,我们显然没办法直接套这个做法。我们先考虑在区间上的做法,再考虑拓展到树上。
我们发现其实我们可以 \(\text{cdq}\) 分治解决这个问题,即每次先递归解决左区间,然后在左区间的凸壳上考虑对于右区间的贡献,然后继续递归解决右区间。可以发现这样做的时间复杂度为 \(\Theta(n\log^2 n)\) 的。
考虑拓展到树上。我们发现其实我们可以用淀粉质解决这个问题,每次我们找到当前子树的重心,假设设为 \(x\) ,我们先递归解决该子树除了 \(x\) 的子树的部分(下面设为 \(S_1\)),那么我们可以考虑 \(S_1\) 对 \(x\) 的子树(下面设为 \(S_2\))产生的贡献,同上文,然后继续递归解决 \(S_2\)。
考虑分析时间复杂度,可以想到每个点的均摊时间复杂度就是点分树上的深度乘上对于一个点更新操作的时间,即为 \(\Theta(\log^2n)\) ,所以总时间复杂度即为 \(\Theta(n\log^2 n)\) 。
有几个细节需要提醒一下,就是说找重心的时候要找最接近于当前子树的根的点,因为这样才能保证不会陷入死循环,具体为什么自己实现一下就可以明白了。另外一个就是这道题目要开 \(\text{long long}\),而且极大值不能赋小了。
\(\texttt{Code}\)
#include <bits/stdc++.h>
using namespace std;
#define INF 0x7f7f7f7f7f7f7f
#define Int register int
#define int long long
#define MAXN 200005
template <typename T> inline void read (T &t){t = 0;char c = getchar();int f = 1;while (c < '0' || c > '9'){if (c == '-') f = -f;c = getchar();}while (c >= '0' && c <= '9'){t = (t << 3) + (t << 1) + c - '0';c = getchar();} t *= f;}
template <typename T,typename ... Args> inline void read (T &t,Args&... args){read (t);read (args...);}
template <typename T> inline void write (T x){if (x < 0){x = -x;putchar ('-');}if (x > 9) write (x / 10);putchar (x % 10 + '0');}
int n,t,toop = 1,f[MAXN],p[MAXN],q[MAXN],l[MAXN],fa[MAXN],to[MAXN],wei[MAXN],nxt[MAXN],dis[MAXN],head[MAXN];
void Add_Edge (int u,int v,int w){to[++ toop] = v,wei[toop] = w,nxt[toop] = head[u],head[u] = toop;}
void getdis (int u){for (Int i = head[u];i;i = nxt[i]) dis[to[i]] = dis[u] + wei[i],getdis (to[i]);}
int top,sta[MAXN];double sl[MAXN];//储存每个点到下一个点的斜率
double Slope (int x,int y){return (f[y] - f[x]) * 1.0 / (dis[y] - dis[x]);}
void ins (int x){
while (top > 1 && sl[top - 1] <= Slope (sta[top],x)) -- top;
sta[++ top] = x,sl[top - 1] = Slope (sta[top - 1],x),sl[top] = -INF;
}
int query (double num){
int l = 1,r = top,ans = 0;
while (l <= r){
int mid = (l + r) >> 1;
if (sl[mid] <= num) ans = mid,r = mid - 1;
else l = mid + 1;
}
return sta[ans];
}
int root,mxsiz,siz[MAXN];bool vis[MAXN];//淀粉质需要的东西
void findroot (int u,int SZ){
siz[u] = 1;int mx = 0;
for (Int i = head[u];i;i = nxt[i]) if (!vis[to[i]]) findroot (to[i],SZ),siz[u] += siz[to[i]],mx = max (mx,siz[to[i]]);
mx = max (mx,SZ - siz[u]);
if (mx <= mxsiz) mxsiz = mx,root = u;
}
int sum,pot[MAXN];
void getpoint (int u){
pot[++ sum] = u;
for (Int i = head[u];i;i = nxt[i]) if (!vis[to[i]]) getpoint (to[i]);
}
bool cmp (int x,int y){return dis[x] - l[x] > dis[y] - l[y];}//按照可以到的祖先深度排序
void work (int now,int SZ){
if (SZ == 1) return ;
mxsiz = INF,findroot (now,SZ);int x = root;
for (Int i = head[x];i;i = nxt[i]) vis[to[i]] = 1,SZ -= siz[to[i]];
work (now,SZ),sum = 0;
for (Int i = head[x];i;i = nxt[i]) getpoint (to[i]);
sort (pot + 1,pot + sum + 1,cmp);int a = x;top = 0;
for (Int i = 1;i <= sum;++ i){
int u = pot[i];
while (a != fa[now] && dis[a] >= dis[u] - l[u]) ins (a),a = fa[a];
if (top){
int k = query (p[u]);
f[u] = min (f[u],f[k] + (dis[u] - dis[k]) * p[u] + q[u]);
}
}
for (Int i = head[x];i;i = nxt[i]) work (to[i],siz[to[i]]);
}
signed main(){
read (n,t);
for (Int i = 2,val;i <= n;++ i) read (fa[i],val,p[i],q[i],l[i]),Add_Edge (fa[i],i,val),f[i] = INF;
getdis (1),work (1,n);
for (Int i = 2;i <= n;++ i) write (f[i]),putchar ('\n');
return 0;
}
题解 [NOI2014]购票的更多相关文章
- [BZOJ3672][UOJ#7][NOI2014]购票
[BZOJ3672][UOJ#7][NOI2014]购票 试题描述 今年夏天,NOI在SZ市迎来了她30周岁的生日.来自全国 n 个城市的OIer们都会从各地出发,到SZ市参加这次盛会. ...
- 【BZOJ 3672】 3672: [Noi2014]购票 (CDQ分治+点分治+斜率优化)**
3672: [Noi2014]购票 Description 今年夏天,NOI在SZ市迎来了她30周岁的生日.来自全国 n 个城市的OIer们都会从各地出发,到SZ市参加这次盛会. 全国 ...
- 【BZOJ3672】[Noi2014]购票 树分治+斜率优化
[BZOJ3672][Noi2014]购票 Description 今年夏天,NOI在SZ市迎来了她30周岁的生日.来自全国 n 个城市的OIer们都会从各地出发,到SZ市参加这次盛会. ...
- BZOJ 3672[NOI2014]购票(树链剖分+线段树维护凸包+斜率优化) + BZOJ 2402 陶陶的难题II (树链剖分+线段树维护凸包+分数规划+斜率优化)
前言 刚开始看着两道题感觉头皮发麻,后来看看题解,发现挺好理解,只是代码有点长. BZOJ 3672[NOI2014]购票 中文题面,题意略: BZOJ 3672[NOI2014]购票 设f(i)f( ...
- $NOI2014$ 购票(斜率优化 点分治)
\(NOI2014\)购票 哇终于可以碰电脑了赶快切些火题找找感觉. 拿到这道题的时候发现简单的斜率优化推一推可以秒掉平方做法,然后一条链也可以做. 然后呢... 卧槽这个在一棵树上怎么办啊. 大力\ ...
- bzoj 3672: [Noi2014]购票 树链剖分+维护凸包
3672: [Noi2014]购票 Time Limit: 30 Sec Memory Limit: 512 MBSubmit: 480 Solved: 212[Submit][Status][D ...
- BZOJ 3672: [Noi2014]购票( 树链剖分 + 线段树 + 凸包 )
s弄成前缀和(到根), dp(i) = min(dp(j) + (s(i)-s(j))*p(i)+q(i)). 链的情况大家都会做...就是用栈维护个下凸包, 插入时暴力弹栈, 查询时就在凸包上二分/ ...
- bzoj千题计划251:bzoj3672: [Noi2014]购票
http://www.lydsy.com/JudgeOnline/problem.php?id=3672 法一:线段树维护可持久化单调队列维护凸包 斜率优化DP 设dp[i] 表示i号点到根节点的最少 ...
- [BZOJ3672][Noi2014]购票 斜率优化+点分治+cdq分治
3672: [Noi2014]购票 Time Limit: 30 Sec Memory Limit: 512 MBSubmit: 1749 Solved: 885[Submit][Status][ ...
随机推荐
- 高德渲染网关Go语言重构实践
1.导读 高德启动Go业务建设已经有段时间了,主要包含Go应用落地,Go中间件建设,云原生三个部分.经过持续的发力,在这些方面取得了不错的进展.高德Go业务落地过程是如何实现的,遇到过哪些问题,如何 ...
- tensorflow 单机多卡 官方cifar10例程
测试了官方历程,看没有问题,加上时间紧任务重,就不深究了. 官方tutorials:https://www.tensorflow.org/tutorials/images/deep_cnn githu ...
- python pip/anaconda使用笔记
Switch to Chinese conda Source, config file is in ~/.condarc conda config --add channels https://mir ...
- linux centos7 tail
2021-08-30 # 不指定行数,默认显示 10 行 # 显示 /var/log/crond 后100行 taile -100 /var/log/crond # 动态显示 /var/log/cro ...
- vue js 手写 正则判断 手机号码 和 密码
const phoneOrEmails = /^1[3|4|5|6|7|8|9][0-9]\d{8}$/ if(this.ruleForms.phoneOrEmail == ...
- 人生重开模拟器「GitHub 热点速览 v.21.36」
作者:HelloGitHub-小鱼干 人生是不能重来的,但是 lifeRestart 能满足你的重开心愿.初始值不满意,你可以一直随机生成或者自动添加颜值.智力.运气值,倒是一种"重生&qu ...
- SQLServer数据库之连接查询
SQLServer数据库之连接查询 表的连接查询的几种方法介绍: inner join on内连接,left join on 左连接 , rigth join on 右连接, full join on ...
- 集合框架3-Arrays 类
Arrays 和 Collections是分别操作数组和集合的两个工具类.今天就来对 Arrays 中的内容作个总结. 一.Arrays 类概述 Arrays 类位于 java.util包中.Arra ...
- Spring(一)——概述
一.概述 1.介绍 struts 是 web 框架 (jsp/action/actionfrom).hibernate是orm (Object Relational Mapping) 框架,处于持久层 ...
- shell运算方式
1.(())--整数运算 [root@m01 /server/scripts]# a=1 [root@m01 /server/scripts]# b=2 [root@m01 /server/scrip ...