文章目录

  • 题目
  • 分析
  • 代码

题目

给一棵第 iii 条边边权为 did_idi​ 的有根树,111 为根。对于每个点 xxx,对于满足如下条件的序列 {s1,⋯,sk}\{s_1,\cdots,s_k\}{s1​,⋯,sk​}:

  1. si−1s_i - 1si​−1 是 sis_isi​ 的祖先,且 si−1≠sis_{i - 1} \neq s_isi−1​​=si​。
  2. s1=xs_1 = xs1​=x 中。

求 ∑i=2k(asi−1−dist(si−1,si))bsi\sum_{i = 2}^k (a_{s_{i - 1}} - \text{dist}(s_{i - 1}, s_i))b_{s_i}∑i=2k​(asi−1​​−dist(si−1​,si​))bsi​​ 的最大值。

1≤n≤106,0≤ai,bi,di≤1091 \leq n \leq 10^6, 0 \leq a_i, b_i, d_i \leq 10^91≤n≤106,0≤ai​,bi​,di​≤109,从 111 出发到每个点的距离不超过 10910^9109,最终答案不超过 2×10172 \times 10^{17}2×1017。

分析

考虑朴素的 DP:dpu=max⁡v∈subtree of udpv+(au−dist(u,v))bvdp_u = \max_{v \in \text{subtree of }u}dp_v + (a_u - \text{dist}(u,v))b_vdpu​=v∈subtree of umax​dpv​+(au​−dist(u,v))bv​ 把 dist\text{dist}dist 用深度表示可以得到 dpu=max⁡v∈subtree of u(dpv+aubv+depubv−depvbv)=max⁡v∈subtree of u((au+depu)bv+dpv−depvbv)\begin{aligned} dp_u =& \max_{v \in \text{subtree of }u} (dp_v + a_ub_v + \text{dep}_ub_v -\text{dep}_vb_v) \\ =& \max_{v \in \text{subtree of }u} ((a_u + \text{dep}_u)b_v + dp_v -\text{dep}_vb_v)\end{aligned}dpu​==​v∈subtree of umax​(dpv​+au​bv​+depu​bv​−depv​bv​)v∈subtree of umax​((au​+depu​)bv​+dpv​−depv​bv​)​ 设函数 fu(x)=bux+dpu−depubuf_u(x) = b_ux + dp_u -\text{dep}_ub_ufu​(x)=bu​x+dpu​−depu​bu​,上式转化为 dpu=max⁡v∈subtree of ufv(au+depu)dp_u = \max_{v \in \text{subtree of }u} f_v(a_u + \text{dep}_u)dpu​=v∈subtree of umax​fv​(au​+depu​) 由于 fu(x)f_u(x)fu​(x) 是一次函数,很容易想到用李超树维护。一开始想的是用 DFN 序转为区间查询,然后发现李超树不能可持久化(求的是最大值,没有可减性),后来发现只需要合并所有子树,再插入当前点对应的直线,就能得到当前点的李超树了,写动态开点李超树,合并两个树 u,vu, vu,v 方法类似于权值线段树:把 vvv 的每个直线插入进 uuu。时间复杂度感觉是 O(nlog⁡2n)O(n \log^2 n)O(nlog2n) 的,然而题解似乎说是 O(nlog⁡n)O(n \log n)O(nlogn) 的,没看懂:

不管了反正加个按秩合并跑的飞快……

代码

#include <algorithm>
#include <cstdio>
#include <cstring>
#include <vector>namespace IO { // 板子是 down 里面发的const int sz = 1 << 22;char a[sz + 5], b[sz + 5], *p1 = a, *p2 = a, *t = b, p[105];inline char gc() {return p1 == p2 ? (p2 = (p1 = a) + fread(a, 1, sz, stdin), p1 == p2 ? EOF : *p1++) : *p1++;}template <class T>T Read() {T x = 0;char c = gc();for (; c < '0' || c > '9'; c = gc());for (; c >= '0' && c <= '9'; c = gc()) x = x * 10 + (c - '0');return x;}inline void flush() { fwrite(b, 1, t - b, stdout), t = b; }inline void pc(char x) {*t++ = x;if (t - b == sz)flush();}template <class T>void Print(T x, char c = '\n') {if (x == 0)pc('0');int t = 0;for (; x; x /= 10) p[++t] = x % 10 + '0';for (; t; --t) pc(p[t]);pc(c);}struct F {~F() { flush(); }} f;
}using IO::Print;
using IO::Read;typedef long long LL;const int MAXN = 1000000;
const LL INF = 1ll << 58;int N, A[MAXN + 5], B[MAXN + 5];struct Edge {int v, w;Edge *nxt;
} E[2 * MAXN + 5], *Adj[MAXN + 5], *EdgeCnt = E;void AddEdge(const int &u, const int &v, const int &w) {(++EdgeCnt)->v = v, EdgeCnt->w = w, EdgeCnt->nxt = Adj[u], Adj[u] = EdgeCnt;
}int Dep[MAXN + 5];struct Line {int k;LL b;Line() {}Line(const int _k, const LL &_b) { k = _k, b = _b; }inline LL Cal(const int &x) const { return (LL)k * x + b; }
} L[MAXN + 5];struct LiChaoTree {int NodeCnt;struct Node {int lch, rch, siz;Line l;} T[MAXN * 30 + 5];void Insert(int &u, const int &lft, const int &rgt, Line cur) {if (!u) {T[u = ++NodeCnt].l = cur;T[u].siz = 1;return;}int mid = ((rgt - lft) >> 1) + lft;if (T[u].l.Cal(mid) < cur.Cal(mid))std::swap(T[u].l, cur);LL lhc = cur.Cal(lft), rhc = cur.Cal(rgt);LL lhu = T[u].l.Cal(lft), rhu = T[u].l.Cal(rgt);if (lhc <= lhu && rhc <= rhu)return;if (lhc > lhu)Insert(T[u].lch, lft, mid, cur);elseInsert(T[u].rch, mid + 1, rgt, cur);T[u].siz = T[T[u].lch].siz + T[T[u].rch].siz;}int Merge(int u, const int &v, const int &lft, const int &rgt) {if (!u || !v)return u ^ v;Insert(u, lft, rgt, T[v].l);int mid = ((rgt - lft) >> 1) + lft;T[u].lch = Merge(T[u].lch, T[v].lch, lft, mid);T[u].rch = Merge(T[u].rch, T[v].rch, mid + 1, rgt);T[u].siz = T[T[u].lch].siz + T[T[u].rch].siz;return u;}LL Query(const int &u, const int &lft, const int &rgt, const int &x) {if (!u) return 0;if (lft == rgt) {  return T[u].l.Cal(x); }LL res = T[u].l.Cal(x);int mid = ((rgt - lft) >> 1) + lft;if (x <= mid) res = std::max(res, Query(T[u].lch, lft, mid, x));else res = std::max(res, Query(T[u].rch, mid + 1, rgt, x));return res;}
} T;int DfnCnt;
int Root[MAXN + 5];LL Dp[MAXN + 5];void Solve(const int &u, const int &f) {for (Edge *i = Adj[u]; i; i = i->nxt) {int v = i->v;if (v == f)continue;Dep[v] = Dep[u] + i->w;Solve(v, u);if (T.T[Root[v]].siz > T.T[Root[u]].siz)std::swap(Root[u], Root[v]);Root[u] = T.Merge(Root[u], Root[v], 0, 2e9);}Dp[u] = T.Query(Root[u], 0, 2e9, A[u] + Dep[u]);T.Insert(Root[u], 0, 2e9, Line(B[u], -(LL)Dep[u] * B[u] + Dp[u]));
}int main() {N = Read<int>();for (int i = 1; i <= N; i++) A[i] = Read<int>(), B[i] = Read<int>();for (int i = 1; i < N; i++) {int u = Read<int>(), v = Read<int>(), w = Read<int>();AddEdge(u, v, w);AddEdge(v, u, w);}Solve(1, 0);for (int i = 1; i <= N; i++) Print(Dp[i]);return 0;
}

[多校 NOIP 联合模拟 11.30 T4] ZZH 的旅行(李超树合并) | 错题本相关推荐

  1. A. [2021.1.29多校省选模拟11]最大公约数(杜教筛/数论)

    A. [2021.1.29多校省选模拟11]最大公约数 这是一个杜教筛的经典题目,最后我们只需要筛一下1∗xμ(x)1*x\mu(x)1∗xμ(x)这个函数的前缀和即可,然后看到有111这个函数,我们 ...

  2. 11.28 限定某个目录禁止解析php 11.29 限制user_agent 11.30/11.31 php相关配置

    - 11.28 限定某个目录禁止解析php - 11.29 限制user_agent - 11.30/11.31 php相关配置 - 扩展 - apache开启压缩 http://ask.apelea ...

  3. JZOJ 3518. 【NOIP2013模拟11.6A组】进化序列(evolve)

    3518. [NOIP2013模拟11.6A组]进化序列(evolve) (File IO): input:evolve.in output:evolve.out Time Limits: 1000 ...

  4. jzoj2702. 探险jzoj3917. 【NOIP2014模拟11.2A组】福慧双修

    Description 探险家小T好高兴!X国要举办一次溶洞探险比赛,获奖者将得到丰厚奖品哦!小T虽然对奖品不感兴趣,但是这个大振名声的机会当然不能错过! 比赛即将开始,工作人员说明了这次比赛的规则: ...

  5. 【NOIP2011模拟11.1】钓鱼

    [NOIP2011模拟11.1]钓鱼 Description 我们把钓鱼的过程放在坐标系里来考虑.图中蓝色的点为船,初始时它的坐标记为(Ax,y).河深为y,河宽为x.某个时刻会从左边界或右边界游出来 ...

  6. 【ybt 入门到进阶模拟赛 Day2 T4】数独游戏

    数独游戏 题目链接:ybt 入门到进阶模拟赛 Day2 T4 题目大意 就要你填一个数独,保证有唯一解. 思路 直接暴力 dfs,不用剪枝优化都可以过. 代码 #include<queue> ...

  7. jozj5945. 【NOIP2018模拟11.02】昆特牌

    5945. [NOIP2018模拟11.02]昆特牌 Description 作为一个资深OIer,你被邀请到位于波兰的CDPR总部参观.但没想到你刚一到就遇到了麻烦.昆特牌的数据库发生了故障.原本昆 ...

  8. 个人面试记录 - 抖音音乐11.13~11.30

    一面 - 11.13晚上八点 自我介绍 redis,多线程lpush的情况下是否会出现数据覆盖问题,为什么? 假设现在有一个场景,不管怎么优化,读取db时间固定为1s,怎么解决? 写一个sql,统计上 ...

  9. pandas使用normalize函数将dataframe中的时间(time)数据列转化为日期(date)数据列(例如,从2019-12-25 11:30:00到2019-12-25)

    pandas使用normalize函数将dataframe中的时间(time)数据列转化为日期(date)数据列(例如,从2019-12-25 11:30:00到2019-12-25) 目录

最新文章

  1. 【文本分类】A C-LSTM Neural Network for Text Classification
  2. 串口编程-读写超时 COMMTIMEOUTS设置
  3. 牛客网平台常州大学新生寒假训练会试
  4. python源代码不需要编译成什么-python程序不需要编译吗
  5. 使用Node.js+Socket.IO搭建WebSocket实时应用
  6. PHP伪类型和伪变量
  7. linux vnc的小黑点和鼠标不同步_vnc连接windows,推荐三款非常好用的vnc连接windows软件...
  8. AAC ADTS格式分析
  9. npm publish npm resource busy or locked 4082 发布出错解决方案
  10. 3dmax如何使用模型快速切片命令
  11. scratch基础讲解与小游戏制作(接水果)
  12. 为了摸鱼,我开发了一个工具网站
  13. 小李飞刀:Python我又来啦,例无虚发~
  14. 【HGNN】北邮循序渐进研究HGNN
  15. [爬虫]字节跳动招聘爬取实战-csrf校验
  16. Ubuntu 18.04 创建 mdadm RAID0
  17. 【实验技术笔记】利用重组载体做基因过表达(pCDH载体)
  18. selenium自动获取王者荣耀英雄海报并保存到本地
  19. 奇葩的公司,奇葩的现象
  20. 神经网络结构图如何看懂,神经网络结构图片

热门文章

  1. 如何训练你的准确率?
  2. Win10 设置取消快速启动栏图标,C++版
  3. RK系列(RK3568) tda7313音频 i2c驱动
  4. 【092】罗马数字 XXII.XI.MMXII
  5. 计算机专业常用图论,计算机专业研究生图论课程探讨.doc
  6. 嵌入式开发必备!Arm Development Studio 安装说明
  7. 河北高级消防设施操作员考试真题及答案解析
  8. 国内SAAS主要网站
  9. 关于ubuntu下的bt下载工具
  10. 26岁,干了三年测试,月薪才12k,能跳槽找到一个更高薪资的工作吗?