link。

朴素 dp 大约就是 \(f_x=f_y+v_x\times(d_x-d_y)+s_x\),\(y\) 是 \(x\) 的祖先。这个式子可以斜率优化,在以 \(d_y\) 为横坐标,\(f_y\) 为纵坐标的坐标系中,斜率为 \(v_x\)。

我们应该用单调栈维护一个到根的树链。由于回溯的时候 \(v_x\) 不一定单调,取 \(f_x\) 的 dp 值时我们应该在完整的凸壳上二分。

插入决策点时,按照普通序列上的斜率优化弹栈(朴素)。很多人的问题是回溯还原栈状态的复杂度,其实你真正修改的值只有插入进去的位置,如果你没有使用 STL 的话弹栈的操作实际上是没有进行的,他们保留在栈中,只需要将栈顶指针还原即可,每次回溯的个数是 \(O(1)\) 级别的。

实际插入决策点时,因为时间复杂度的问题需要二分插入位置。如果你以乘代除,注意开 __int128

#include<bits/stdc++.h>
#define cmin(x, y) x = std::min(x, y)
#define cmax(x, y) x = std::max(x, y)
#define fors(i, l, r, ...) for(int i = (l), REP##i = (r), ##__VA_ARGS__; i <= REP##i; ++i)
#define dfors(i, r, l, ...) for(int i = (r), REP##i = (l), ##__VA_ARGS__; i >= REP##i; --i)
typedef long long ll;
int n, q[100100], l = 1, r;
ll f[100100], v[100100], s[100100], d[100100];
std::vector<std::pair<int, ll>> e[100100];
void pre_dfs(const int x, int fa) {
for(const auto [y, w] : e[x]) if(y != fa) d[y] = d[x]+w,pre_dfs(y, x);
}
ll up(const int i, const int j) { return f[j]-f[i]; }
ll down(const int i, const int j) { return d[j]-d[i]; }
ll cal(const int i, const int j) { return f[j]+v[i]*(d[i]-d[j])+s[i]; }
int bisect_optimal_decision(const ll k) {
int l = ::l, r = ::r, res = l; l++;
for(int mid; l <= r;) {
mid = (l+r)>>1;
if(up(q[mid-1], q[mid]) <= (__int128)k*down(q[mid-1], q[mid])) l = mid+1,res = mid;
else r = mid-1;
}
return q[res];
}
int bisect_insert_position(const int x) {
int l = ::l, r = ::r, res = l; l++;
for(int mid; l <= r;) {
mid = (l+r)>>1;
if((__int128)up(q[mid-1], q[mid])*down(q[mid], x) <= (__int128)up(q[mid], x)*down(q[mid-1], q[mid])) l = mid+1,res = mid;
else r = mid-1;
}
return res;
}
void dp_dfs(const int x, const int fa) {
if(x != 1) f[x] = cal(x, bisect_optimal_decision(v[x]));
int _r = r, t, tt;
r = bisect_insert_position(x);
t = r+1,tt = q[r+1],q[++r] = x;
for(const auto [y, w] : e[x]) if(y != fa) dp_dfs(y, x);
q[t] = tt,r = _r;
}
signed main() {
std::ios_base::sync_with_stdio(0);
std::cin.tie(0);
std::cin >> n;
fors(i, 1, n-1, x, y, z) {
std::cin >> x >> y >> z;
e[x].emplace_back(y, z);
e[y].emplace_back(x, z);
}
fors(i, 2, n) std::cin >> s[i] >> v[i];
pre_dfs(1, 0),dp_dfs(1, 0);
fors(i, 2, n) std::cout << f[i] << " \n"[i == n];
return 0;
}

「ceoi 2009」harbingers的更多相关文章

  1. 「BZOJ 1297」「SCOI 2009」迷路「矩阵乘法」

    题意 边权\(w \in [1, 9]\)的\(n\)个结点的有向图,图上从\(1\)到\(n\)长度为\(d\)的路径计数,\(n \leq 10\). 题解 如果边权为\(1\)很经典,设\(f[ ...

  2. 「SDOI 2009」Elaxia的路线

    发现自己这几天智商完全不在线-- 这道题的数据十分的水,怎样都可以艹过去-- 开始想了一个完全错误的算法,枚举一对点,判断这一对点是否同时在两条最短路上,是就用两点之间的路径更新答案.显然这样是错的: ...

  3. 「BZOJ 1876」「SDOI 2009」SuperGCD「数论」

    题意 求\(\gcd(a, b)\),其中\(a,b\leq10^{10000}\) 题解 使用\(\text{Stein}\)算法,其原理是不断筛除因子\(2\)然后使用更相减损法 如果不筛\(2\ ...

  4. Solution -「CEOI 2017」「洛谷 P4654」Mousetrap

    \(\mathscr{Description}\)   Link.   在一个含 \(n\) 个结点的树形迷宫中,迷宫管理者菈米莉丝和一只老鼠博弈.老鼠初始时在结点 \(y\),有且仅有结点 \(x\ ...

  5. Solution -「CEOI 2006」「洛谷 P5974」ANTENNA

    \(\mathcal{Description}\)   Link.   给定平面上 \(n\) 个点,求最小的能覆盖其中至少 \(m\) 个点的圆半径及一个可能的圆心.   \(n\le500\),坐 ...

  6. Solution -「HNOI 2009」「洛谷 P4727」图的同构计数

    \(\mathcal{Description}\)   Link.   求含 \(n\) 个点的无标号简单无向图的个数,答案模 \(997\). \(\mathcal{Solution}\)   首先 ...

  7. NLP领域的ImageNet时代到来:词嵌入「已死」,语言模型当立

    http://3g.163.com/all/article/DM995J240511AQHO.html 选自the Gradient 作者:Sebastian Ruder 机器之心编译 计算机视觉领域 ...

  8. 前端构建工具之gulp(一)「图片压缩」

    前端构建工具之gulp(一)「图片压缩」 已经很久没有写过博客了,现下终于事情少了,开始写博吧 今天网站要做一些优化:图片压缩,资源合并等 以前一直使用百度的FIS工具,但是FIS还没有提供图片压缩的 ...

  9. fir.im Weekly - 如何打造 Github 「爆款」开源项目

    最近 Android 转用 Swift 的传闻甚嚣尘上,Swift 的 Github 主页上已经有了一次 merge>>「Port to Android」,让我们对 Swift 的想象又多 ...

  10. 更新日志 - fir.im「高级统计」功能上线

    距离 2016 年到来只剩 10 个日夜,fir.im 也准备了一些新鲜的东西,比如「高级统计」功能和「跳转应用商店」功能,帮助你更好地管理.优化应用,欢迎大家试用反馈:) 新增高级统计功能 这次更新 ...

随机推荐

  1. C++面试八股文:在C++中,有哪些可执行体?

    某日二师兄参加XXX科技公司的C++工程师开发岗位第14面: 面试官:在C++中,有哪些可执行体? 二师兄:可执行体? 面试官:也就是可调用对象. 二师兄:让我想一想.函数.函数指针.类的静态方法.类 ...

  2. A First course in FEM —— matlab代码实现求解传热问题(稳态)

    这篇文章会将FEM全流程走一遍,包括网格.矩阵组装.求解.后处理.内容是大三时的大作业,今天拿出来回顾下. 1. 问题简介 涡轮机叶片需要冷却以提高涡轮的性能和涡轮叶片的寿命.我们现在考虑一个如上图所 ...

  3. GPT3与机器翻译的结合:探索新的语言翻译技术

    目录 引言 随着全球化的加速和人工智能的快速发展,机器翻译成为了许多企业.机构和个人的痛点.虽然已有多种机器翻译技术,但基于自然语言处理和深度学习的机器翻译一直缺乏有效的解决方案,这导致机器翻译的准确 ...

  4. mysql where和having的用法例子

    结论:想在分组之后在进行过滤就要使用having了,如果只是对指定的行进行过滤的话,那么就需要使用where了

  5. Solon Web 也支持响应式开发了?!

    "solon.web.flux" 是 solon v2.3.6 新推出的生态插件,为 solon web 提供响应式接口支持 (io.projectreactor) .为什么叫这个 ...

  6. Python开发中自动化构建项目结构样式

    摘要:在项目开发过程中,一个良好的项目结构对于团队的协作和代码的可维护性起着重要作用.通过使用自动生成项目结构文字样式的工具.不仅节省了手动编写项目结构的麻烦,还确保了结构的一致性和准确性. 本文分享 ...

  7. C++笔记(1)——类的基本概念知识

    C#和C++的部分面向对象方式类似,只记录不同点. 定义类与关键字: 下面是C++类的定义方式与C++关键字public和private的表达方式: class Box { private: // 私 ...

  8. Windows10 下 Neo4j1.5.8 安装教程

    前言 Neo4j 是一个高性能的.NOSQL 图形数据库,它将结构化数据存储在网络上而不是表中.基于磁盘的.具备完全的事务特性的 Java 持久化引擎,这里就不把他和常用关系型数据库做对比了.因为篇幅 ...

  9. 微服务探索之路06篇k8s配置文件Yaml部署Redis使用Helm部署MongoDB和kafka

    1 安装Redis 1.1创建配置文件redis.conf 切换到自己的目录下如本文是放在/home/ubuntu下 cd /home/ubuntu vim redis.conf bind 0.0.0 ...

  10. java使用apache.poi导出word文件

    功能说明: 将试卷导出word,并可以打印,装订,效果图: 下面是实现代码: package com.xxxxx.business.course.utils; import com.alibaba.f ...