题解 [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][ ...
随机推荐
- call bind apply的区别
call() 和apply()的第一个参数相同,就是指定的对象.这个对象就是该函数的执行上下文. call()和apply()的区别就在于,两者之间的参数. call()在第一个参数之后的 后续所有参 ...
- 自己封装一个Object.freeze()方法
1.遍历所有属性和方法 2.修改遍历到的属性的描述 3.Object.seal() Object.defineProperty(Object,'freezePolyfill',{ value:func ...
- 移动端 uni-app 滑动事件 精确判断手指滑动方向
移动端根据手指滑动操作判断滑动方向 设计思路: 1.根据移动端touchstart和touchend方法获取手指触摸屏幕的开始坐标和结束坐标 2.根据两个坐标计算与水平方向的夹角 3.根据夹角判断当前 ...
- 搭建本地yum源出现:mount: 在 /dev/sr0 上找不到媒体
2021-07-27 在练习环境搭建时,因为是离线环境,故先搭建本地yum源,但是出现了一个往常没有的问题:mount: 在 /dev/sr0 上找不到媒体,参考其他博主的文章得到解决方法. 排查问题 ...
- system的使用
<stdio.h> std是一个标准库,i =input o =output 标准输入输出库 .h头文件 system的使用 功能:在已经运行的程序 ...
- vue ele 表单规则校验俩次输入密码是否相同,校验手机号 ( 前端小课堂:小细节,大进步 )
这个是密码的拦截 : [{ required: true, validator: validatePass4, trigger: "blur" }], 同级关系下写下方法,类 ...
- RabbitMQ-进阶
目录 过期时间TTL 设置队列TTL 消息确认机制的配置 死信队列 内存磁盘的监控 RabbitMQ的内存控制 命令的方式 配置文件方式 rabbitmq.conf RabbitMQ的内存换页 Rab ...
- Python - 面向对象编程 - 小实战(1)
题目 设计一个类Person,生成若干实例,在终端输出如下信息 小明,10岁,男,上山去砍柴 小明,10岁,男,开车去东北 小明,10岁,男,最爱大保健 老李,90岁,男,上山去砍柴 老李,90岁,男 ...
- 【曹工杂谈】Maven IOC容器的下半场:Google Guice
Maven容器的下半场:Guice 前言 在前面的文章里,Maven底层容器Plexus Container的前世今生,一代芳华终落幕,我们提到,在Plexus Container退任后,取而代之的底 ...
- Python - poetry(3)配置项详解
config 命令 poetry 通过 config 命令进行配置 也可以直接在 config.toml 文件中进行配置,该文件将在首次运行该命令时自动创建 文件目录 macOS:~/Library/ ...