LOJ 题面传送门

orz 斜率优化……

模拟赛时被这题送走了,所以来写篇题解(

首先这个最短路的求法是 trivial 的,直接一遍 dijkstra 即可(

重点在于怎样求第二问。注意到这个第二问平方和最大要在保证最短路的基础上求,因此考虑建出最短路 DAG,这样最短路径上一条 \(1\to n\) 的路径就对应原图中一条最短路。因此此题等价于求一条 \(1\to n\) 的路径,满足每一个属于同一连续段上路径权值和的平方之和最大。注意到 \(f(x)=x^2\) 是下凸函数,也就是对于一段同一铁路线上的路径,我们肯定不会选择将它们拆成一段段小路径。因此我们考虑这样一个 \(dp\):\(dp_i\) 表示从 \(1\to i\) 路径上每一段权值之和的平方之和的最大值,转移就枚举上一次乘坐的那段铁路线的起始城市 \(j\),由于是最短路径 DAG,必然有这一段路径的长度为 \(dis_j-dis_i\),因此有转移 \(dp_i=\max\{dp_j+(dis_j-dis_i)^2\}\)。

直接做是 \(\sum s_i^2\) 的无法通过,考虑怎样优化。考虑将平方拆开来得到 \(dp_i=\max\{dp_j+dis_j^2-2dis_idis_j\}+dis^2_i\),这东西等价于平面上有若干个形如 \((dis_j,dp_j+dis_j^2)\) 的点,现在你要过这些点分别做斜率 \(2dis_i\) 的直线并取最大截距。我们考虑对所有铁路线维护这些点组成的上凸包,查询就直接在凸包中二分找斜率为 \(2dis_i\) 的直线也可以。当然也有线性的维护方法,注意到此题我们需维护上凸包,凸包中直线斜率递减,并且在拓扑排序的过程中我们查询的直线的斜率 \(2dis_i\) 肯定是递增的,因此每查询一条直线毙掉的凸包中的直线肯定一段后缀,也就是最新加入的某一些直线,因此需用单调栈维护。复杂度 \(n\log n\)。

const int MAXN=1e6;
int n,m,hd[MAXN+5],to[MAXN+5],nxt[MAXN+5],val[MAXN+5],ec=0;
void adde(int u,int v,int w){to[++ec]=v;val[ec]=w;nxt[ec]=hd[u];hd[u]=ec;}
vector<pii> tr[MAXN+5],pos[MAXN+5];
vector<int> bel[MAXN+5];
ll dis[MAXN+5],dp[MAXN+5];
int ord[MAXN+5],bcnt=0;
bool cmp(int x,int y){return dis[x]<dis[y];}
ld slope(int x,int y){return 1.0*((dis[x]*dis[x]+dp[x])-(dis[y]*dis[y]+dp[y]))/(dis[x]-dis[y]);}
vector<int> stk[MAXN*2+5];
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++){
int cnt,x;scanf("%d%d",&cnt,&x);
tr[i].pb(mp(x,0));int pre=x;pos[x].pb(mp(i,0));
for(int j=1;j<=cnt;j++){
int w,y;scanf("%d%d",&w,&y);
tr[i].pb(mp(y,w));pos[y].pb(mp(i,j));
adde(pre,y,w);pre=y;
} bel[i].resize(cnt+2);
} memset(dis,63,sizeof(dis));dis[1]=0;
priority_queue<pair<ll,int>,vector<pair<ll,int> >,greater<pair<ll,int> > > q;
q.push(mp(0,1));
while(!q.empty()){
pair<ll,int> p=q.top();q.pop();int x=p.se;
for(int e=hd[x];e;e=nxt[e]){
int y=to[e],z=val[e];
if(dis[y]>dis[x]+z){
dis[y]=dis[x]+z;
q.push(mp(dis[y],y));
}
}
}
for(int i=1;i<=n;i++) ord[i]=i;
sort(ord+1,ord+n+1,cmp);
for(int i=1;i<=m;i++) bel[i][0]=++bcnt;
for(int i=1;i<=n;i++){
int x=ord[i];//printf("%d\n",x);
for(pii p:pos[x]){
int id=p.fi,t=p.se;if(!t) continue;
int pre=tr[id][t-1].fi;
if(dis[x]==dis[pre]+tr[id][t].se) bel[id][t]=bel[id][t-1];
else bel[id][t]=++bcnt;
// printf("%d %d %d %d\n",x,id,t,bel[id][t]);
if(bel[id][t]==bel[id][t-1]){
int b=bel[id][t];
assert(!stk[b].empty());
while(stk[b].size()>=2&&slope(stk[b][stk[b].size()-1],stk[b][stk[b].size()-2])<2*dis[x]) stk[b].ppb();
int y=stk[b].back();chkmax(dp[x],dp[y]+(dis[x]-dis[y])*(dis[x]-dis[y]));
}
}
for(pii p:pos[x]){
int id=p.fi,t=p.se,b=bel[id][t];
// printf("ins %d\n",b);
while(stk[b].size()>=2&&slope(stk[b][stk[b].size()-1],stk[b][stk[b].size()-2])<
slope(stk[b][stk[b].size()-1],x)) stk[b].ppb();
stk[b].pb(x);
}
} printf("%lld %lld\n",dis[n],dp[n]);
return 0;
}

LOJ #2769 -「ROI 2017 Day 1」前往大都会(单调栈维护斜率优化)的更多相关文章

  1. Loj#2769-「ROI 2017 Day 1」前往大都会【最短路树,斜率优化】

    正题 题目链接:https://loj.ac/p/2769 题目大意 给出\(n\)个点\(m\)条地铁线路,每条线路是一条路径. 求\(1\)到\(n\)的最短路且在最短路径的情况下相邻换乘点的距离 ...

  2. [LOJ#6259]「CodePlus 2017 12 月赛」白金元首与独舞

    [LOJ#6259]「CodePlus 2017 12 月赛」白金元首与独舞 试题描述 到河北省 见斯大林 / 在月光下 你的背影 / 让我们一起跳舞吧 うそだよ~ 河北省怎么可能有 Stalin. ...

  3. loj #6250. 「CodePlus 2017 11 月赛」找爸爸

    #6250. 「CodePlus 2017 11 月赛」找爸爸 题目描述 小 A 最近一直在找自己的爸爸,用什么办法呢,就是 DNA 比对. 小 A 有一套自己的 DNA 序列比较方法,其最终目标是最 ...

  4. [LOJ 6249]「CodePlus 2017 11 月赛」汀博尔

    Description 有 n 棵树,初始时每棵树的高度为 H_i,第 i 棵树每月都会长高 A_i.现在有个木料长度总量为 S 的订单,客户要求每块木料的长度不能小于 L,而且木料必须是整棵树(即不 ...

  5. [LOJ 6248]「CodePlus 2017 11 月赛」晨跑

    Description “无体育,不清华”.“每天锻炼一小时,健康工作五十年,幸福生活一辈子” 在清华,体育运动绝对是同学们生活中不可或缺的一部分.为了响应学校的号召,模范好学生王队长决定坚持晨跑.不 ...

  6. loj 2392「JOISC 2017 Day 1」烟花棒

    loj 答案显然满足二分性,先二分一个速度\(v\) 然后显然所有没有点火的都会往中间点火的人方向走,并且如果两个人相遇不会马上点火,要等到火快熄灭的时候才点火,所以这两个人之后应该在一起行动.另外有 ...

  7. loj#2391 「JOISC 2017 Day 1」港口设施

    分析 https://yhx-12243.github.io/OI-transit/records/uoj356%3Bloj2391%3Bac2534.html 代码 #include<bits ...

  8. LOJ 2288「THUWC 2017」大葱的神力

    LOJ 2288「THUWC 2017」大葱的神力 Link Solution 比较水的提交答案题了吧 第一个点爆搜 第二个点爆搜+剪枝,我的剪枝就是先算出 \(mx[i]\) 表示选取第 \(i \ ...

  9. Loj #2731 「JOISC 2016 Day 1」棋盘游戏

    Loj 2731 「JOISC 2016 Day 1」棋盘游戏 JOI 君有一个棋盘,棋盘上有 \(N\) 行 \(3\) 列 的格子.JOI 君有若干棋子,并想用它们来玩一个游戏.初始状态棋盘上至少 ...

随机推荐

  1. Linux常用命令,查看树形结构、删除目录(文件夹)、创建文件、删除文件或目录、复制文件或目录(文件夹)、移动、查看文件内容、权限操作

    5.查看树结构(tree) 通常情况下系统未安装该命令,需要yum install -y tree安装 直接使⽤tree显示深度太多,⼀般会使⽤ -L选项⼿⼯设定⽬录深度 格式:tree -L n [ ...

  2. QQ消算轰炸,我好无聊真的

    from pynput.keyboard import Key,Controller import time from random import choice time.sleep(5) # 创建键 ...

  3. 零基础入门该如何实现C 语言面向对象编程(很有帮助)

    零基础如果更快更好的入门C语言,如何在枯燥的学习中找到属于自己的兴趣,如果把学习当成一种事务性的那以后的学习将会很难有更深入的进步,如果带着乐趣来完成学习那将越学越有意思这样才会让你有想要更深入学习的 ...

  4. 查看VCS版本的指令

    以本人电脑的安装目录为例:在任意path下打开terminal执行命令行/usr/local/vcs2018/bin/vlogan -ID -full64 /usr/local/vcs2018为VCS ...

  5. 转载:使用Xilinx IP核进行PCIE开发学习笔记(一)简介篇

    https://zhuanlan.zhihu.com/p/32786076 最近接触到一个项目,需要使用PCIE协议,项目要求完成一个pcie板卡,最终可以通过电脑进行通信,完成电脑发送的指令.这当中 ...

  6. java线程同步以及对象锁和类锁解析(多线程synchronized关键字)

    一.关于线程安全 1.是什么决定的线程安全问题? 线程安全问题基本是由全局变量及静态变量引起的. 若每个线程中对全局变量.静态变量只有读操作,而无写操作,一般来说,这个全局变量是线程安全的:若有多个线 ...

  7. 绚丽的色彩从何而来_LOTO示波器实测WS2812B系LED光源

    绚丽的色彩从何而来_LOTO示波器实测WS2812B系LED光源 不管你对 "RGB性能狂升300%" 的梗认同不认同,不可否认,绚丽的彩色很是酷炫,在现在市面上带"灯& ...

  8. QuantumTunnel:协议路由 vs 端口路由

    本篇来聊一下内网穿透中流量转发的问题 内网穿透和核心逻辑是根据流量的路由信息准确地将公网流量路由到指定的机器端口上,从而完成一次流量的内网穿透. 这里有一个核心问题,路由信息从哪里获取? 常见的有将路 ...

  9. httprunner3源码解读(4)parser.py

    源码结构目录 可以看到此模块定义了4个属性和12个函数,我们依次来讲解 属性源码分析 # 匹配http://或https:// absolute_http_url_regexp = re.compil ...

  10. Qt 使用大神插件快速创建树状导航栏

    前言 本博客仅仅记录自己的采坑过程以及帮助网友避坑,方便以后快速使用自定义控件,避免重复出错. 下载插件 大神 Github Qt 自定义控件项目地址:https://github.com/feiya ...