[unknown OJ] ZZH的旅行
一、题目
点此看题
二、解法
设 d p [ i ] dp[i] dp[i] 为 i i i 点的最大有趣度,转移很显然啊:
d p [ i ] = d p [ j ] + ( a [ i ] + d [ i ] − d [ j ] ) b [ j ] ( j ∈ s o n i ) dp[i]=dp[j]+(a[i]+d[i]-d[j])b[j]\space\space(j\in son_i) dp[i]=dp[j]+(a[i]+d[i]−d[j])b[j] (j∈soni)然后这个柿子是 O ( n 2 ) O(n^2) O(n2) 的,一眼望过去肯定的决策单调性之类的题了,可以尝试斜率优化:
d p [ j ] + ( a [ i ] + d [ i ] − d [ j ] ) b [ j ] > d p [ k ] + ( a [ i ] + d [ i ] − d [ k ] ) b [ k ] dp[j]+(a[i]+d[i]-d[j])b[j]>dp[k]+(a[i]+d[i]-d[k])b[k] dp[j]+(a[i]+d[i]−d[j])b[j]>dp[k]+(a[i]+d[i]−d[k])b[k] d p [ j ] − d [ j ] b [ j ] − d p [ k ] + d [ k ] b [ k ] b [ j ] − b [ k ] > − ( a [ i ] + d [ i ] ) \frac{dp[j]-d[j]b[j]-dp[k]+d[k]b[k]}{b[j]-b[k]}>-(a[i]+d[i]) b[j]−b[k]dp[j]−d[j]b[j]−dp[k]+d[k]b[k]>−(a[i]+d[i])但是由于 b b b 没有单调性,所以要用平衡树维护凸包,还要启发式合并,所以时间复杂度 O ( n log 2 n ) O(n\log^2 n) O(nlog2n)
其实上面就足以通过此题了,但十分难写,这里不妨再介绍一种李超树的做法。
大家都知道李超树是维护一次函数之类的,我们不妨把问题这样转化:在 i i i 的子树中维护若干条直线: y = b [ j ] x + d p [ j ] − d [ j ] b [ j ] y=b[j]x+dp[j]-d[j]b[j] y=b[j]x+dp[j]−d[j]b[j],我们要求的是 x = a [ i ] + d [ i ] x=a[i]+d[i] x=a[i]+d[i] 处最大的 y y y 值,那么就是李超树板题了:跟线段游戏一模一样。
这次我还想说的是复杂度证明,咋看上去还是要启发式合并和插入,那么不是 O ( n log 2 n ) O(n\log^2 n) O(nlog2n) 的吗?其实不然,因为我们维护的是直线,所以相当于是对全局进行修改,知道李超树修改方式的同学就知道这一部分是 O ( n log n ) O(n\log n) O(nlogn) 的。
但启发式合并中不是还要套上插入吗,这里我们就需要用到全局的思想,因为李超树下传之后会砍掉一半,所以总的修改次数是 O ( n log n ) O(n\log n) O(nlogn),这和启发式合并的 O ( n log n ) O(n\log n) O(nlogn) 是相互独立的,所以总的复杂度是 O ( n log n ) O(n\log n) O(nlogn) 。 b t w , \tt btw, btw, 线段树合并因为话多少个 O ( 1 ) O(1) O(1) 就减少了多少个点,所以时间复杂度才是 O ( n log n ) O(n\log n) O(nlogn) 的
#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
#define int long long
const int M = 1000005;
const int N = 20000005;
const int inf = 2e18;
int read()
{int x=0,f=1;char c;while((c=getchar())<'0' || c>'9') {if(c=='-') f=-1;}while(c>='0' && c<='9') {x=(x<<3)+(x<<1)+(c^48);c=getchar();}return x*f;
}
int n,tot,cnt,f[M],a[M],b[M],d[M],rt[M],dp[M],p[M],ls[N],rs[N];
struct node
{int k,b;node(int K=0,int B=-inf) : k(K) , b(B) {}int ask(int x){return x*k+b;}
}tr[N];
struct edge
{int v,c,next;edge(int V=0,int C=0,int N=0) : v(V) , c(C) , next(N) {}
}e[2*M];
void insert(int &x,int l,int r,node b)
{if(b.ask(p[l])==-inf) return ;if(!x) x=++cnt;int mid=(l+r)>>1;if(b.ask(p[mid])>tr[x].ask(p[mid])){if(tr[x].ask(p[l])>b.ask(p[l])) insert(ls[x],l,mid,tr[x]);if(tr[x].ask(p[r])>b.ask(p[r])) insert(rs[x],mid+1,r,tr[x]); tr[x]=b;}else{if(tr[x].ask(p[l])<b.ask(p[l])) insert(ls[x],l,mid,b);if(tr[x].ask(p[r])<b.ask(p[r])) insert(rs[x],mid+1,r,b);}
}
int merge(int x,int y,int l,int r)
{if(!x || !y) return x+y;int mid=(l+r)>>1;ls[x]=merge(ls[x],ls[y],l,mid);rs[x]=merge(rs[x],rs[y],mid+1,r);insert(x,l,r,tr[y]);return x;
}
int ask(int x,int l,int r,int id)
{if(!x) return -inf;int mid=(l+r)>>1,t=tr[x].ask(p[id]);if(l==r) return t;if(mid>=id) return max(t,ask(ls[x],l,mid,id));return max(t,ask(rs[x],mid+1,r,id));
}
void pre(int u,int fa)
{for(int i=f[u];i;i=e[i].next){int v=e[i].v,c=e[i].c;if(v==fa) continue;d[v]=d[u]+c;pre(v,u);}
}
void dfs(int u,int fa)
{for(int i=f[u];i;i=e[i].next){int v=e[i].v;if(v==fa) continue;dfs(v,u);rt[u]=merge(rt[u],rt[v],1,n);}int id=lower_bound(p+1,p+1+n,a[u]+d[u])-p; dp[u]=max(0ll,ask(rt[u],1,n,id));int K=b[u],B=dp[u]-d[u]*b[u];insert(rt[u],1,n,node(K,B));
}
signed main()
{//freopen("journey.in","r",stdin);//freopen("journey.out","w",stdout);n=read();for(int i=1;i<=n;i++)a[i]=read(),b[i]=read();for(int i=1;i<n;i++){int u=read(),v=read(),c=read();e[++tot]=edge(v,c,f[u]),f[u]=tot;e[++tot]=edge(u,c,f[v]),f[v]=tot;}pre(1,0);for(int i=1;i<=n;i++)p[i]=d[i]+a[i];sort(p+1,p+1+n);//要排序 dfs(1,0);for(int i=1;i<=n;i++)printf("%lld\n",dp[i]);
}
/*
dp[i]=dp[j]+(a[i]+d[i]-d[j])b[j]
那么维护 b[j]x+dp[j]-d[j]b[j]
求x=a[i]+d[i]在最大值y
*/
[unknown OJ] ZZH的旅行相关推荐
- [unknown OJ] ZZH与计数
一.题目 点此看题 二.解法 这题我一开始是想的设 d p [ i ] dp[i] dp[i] 为数 i i i 有多少个的期望,然后跑矩阵乘法可以做到 O ( 2 3 n log m ) O(2 ...
- [unknown OJ] ZZH与背包
一.题目 点此看题 二.解法 一看就是折半搜索,但是左边要排序右边要二分的,O(220×qlog)O(2^{20}\times q\log)O(220×qlog) 这种题往往就是卡掉排序的复杂度,我 ...
- 【李超树】李超线段树维护凸包(凸壳) (例题:blue mary开公司+线段游戏+ZZH的旅行)
文章目录 前言 李超树 引入(斜率优化) 什么是李超树? 李超树活着能干点什么? 算法思想(使用手册?) 插入 查询 模板 判断是否覆盖(优不优) 插入 查询 例题 板题:BlueMary开公司 分析 ...
- [unknown OJ] 客星璀璨之夜
一.题目 点此看题 二.解法 这个样例我佛了,第二个等差数列,第三个等等差数列,没把我考试的错误测出来. 直接讲正解,设dp[i][j]dp[i][j]dp[i][j]为行星iii到jjj,把他们撞完 ...
- [unknown OJ] 养花
一.题目 点此看题 二.解法 可以按照kkk分块,假设界限是SSS,假设值域是VVV 对于不足SSS的情况,可以暴力处理,建出线段树的时间花费是O(nS)O(nS)O(nS)的,查询是O(qlogn ...
- [多校 NOIP 联合模拟 11.30 T4] ZZH 的旅行(李超树合并) | 错题本
文章目录 题目 分析 代码 题目 给一棵第 iii 条边边权为 did_idi 的有根树,111 为根.对于每个点 xxx,对于满足如下条件的序列 {s1,⋯,sk}\{s_1,\cdots,s_k ...
- 在vs code中使用yarn报错 - 无法加载文件 C:\Users\zzh\AppData\Roaming\npm\yarn.ps1
yarn : 无法加载文件 C:\Users\zzh\AppData\Roaming\npm\yarn.ps1,因为在此系统上禁止运行脚本.有关详细信 息,请参阅 http://go.microsof ...
- Team Task:DP
我分到的任务是看ppt--so这篇blog大概就是我的任务进度了?好像还混杂了一些奇怪的求助-- 提纲篇 又名如何高效看PPT? 动态规划优化.pdf By ExfJoe 2018/4/11 14: ...
- 百度云此链接内容可能涉及侵权,分享的文件已经被取消等屏蔽问题的解决方法
朋友刚分享给你的百度云链接,分享的文件存在没有问题,却出现了下面两种情况 情况一:提示[此链接内容可能涉及侵权.色情.反动.低俗等信息,无法访问] 解决: 方法一:将分享的文件名称进行修改. 方法二: ...
最新文章
- php签名是做什么用的,这个签名在PHP中意味着什么()?
- gRPC异步处理应答
- 【php】使用gdb调试php程序
- 【AI视野·今日CV 计算机视觉论文速览 第204期】Mon, 24 May 2021
- 4.Java 面试题整理(JSP 篇)
- 互联网系统架构的演进
- 谢菲尔德大学的MATLAB遗传算法工具箱(附代码文件)
- 通过网店管家抓取奇门淘系订单数据
- google 翻译 tts 语音 tk tkk代码
- 专题讲座3 数论+博弈论 学习心得
- Excel单元格下拉选择,单元格自动计算
- gitLab注册There was an error with the reCAPTCHA. Please solve the reCAPTCHA again.
- Edge浏览器打不开网页解决方法教学
- 百练 4118 开餐馆
- ad板子挖孔_用AD软件画孔的注意了!
- Dynamic DMA mapping Guide
- ubuntu网络无法连接
- Oracle安装时物理内存检查失败的解决方案:
- 服务器1075错误服务修复,错误1075:依存服务不存在,或已标记为删除
- 为什么用「void 0」代替「undefined」
热门文章
- 境外服务器可以做新闻网站吗,租用境外服务器对网站SEO有影响么?影响在哪里?...
- eclipse的中文化
- iphone快捷指令一键重启_一键重启捷径怎么设置 一键重启捷径设置教程
- php1技术论坛,PHP 基础知识-1
- 史上“最”简单的扫雷(16*16 40雷)
- 【deepin15.9】有道云笔记页面卡死解决办法
- 工业ERP系统特点和优势有哪些?
- Gitlab 数据备份
- 第十二部分 项目相关方管理
- SharpDevelop中文本编辑器设置背景色和字体