LOJ #2769 -「ROI 2017 Day 1」前往大都会(单调栈维护斜率优化)
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」前往大都会(单调栈维护斜率优化)的更多相关文章
- Loj#2769-「ROI 2017 Day 1」前往大都会【最短路树,斜率优化】
正题 题目链接:https://loj.ac/p/2769 题目大意 给出\(n\)个点\(m\)条地铁线路,每条线路是一条路径. 求\(1\)到\(n\)的最短路且在最短路径的情况下相邻换乘点的距离 ...
- [LOJ#6259]「CodePlus 2017 12 月赛」白金元首与独舞
[LOJ#6259]「CodePlus 2017 12 月赛」白金元首与独舞 试题描述 到河北省 见斯大林 / 在月光下 你的背影 / 让我们一起跳舞吧 うそだよ~ 河北省怎么可能有 Stalin. ...
- loj #6250. 「CodePlus 2017 11 月赛」找爸爸
#6250. 「CodePlus 2017 11 月赛」找爸爸 题目描述 小 A 最近一直在找自己的爸爸,用什么办法呢,就是 DNA 比对. 小 A 有一套自己的 DNA 序列比较方法,其最终目标是最 ...
- [LOJ 6249]「CodePlus 2017 11 月赛」汀博尔
Description 有 n 棵树,初始时每棵树的高度为 H_i,第 i 棵树每月都会长高 A_i.现在有个木料长度总量为 S 的订单,客户要求每块木料的长度不能小于 L,而且木料必须是整棵树(即不 ...
- [LOJ 6248]「CodePlus 2017 11 月赛」晨跑
Description “无体育,不清华”.“每天锻炼一小时,健康工作五十年,幸福生活一辈子” 在清华,体育运动绝对是同学们生活中不可或缺的一部分.为了响应学校的号召,模范好学生王队长决定坚持晨跑.不 ...
- loj 2392「JOISC 2017 Day 1」烟花棒
loj 答案显然满足二分性,先二分一个速度\(v\) 然后显然所有没有点火的都会往中间点火的人方向走,并且如果两个人相遇不会马上点火,要等到火快熄灭的时候才点火,所以这两个人之后应该在一起行动.另外有 ...
- loj#2391 「JOISC 2017 Day 1」港口设施
分析 https://yhx-12243.github.io/OI-transit/records/uoj356%3Bloj2391%3Bac2534.html 代码 #include<bits ...
- LOJ 2288「THUWC 2017」大葱的神力
LOJ 2288「THUWC 2017」大葱的神力 Link Solution 比较水的提交答案题了吧 第一个点爆搜 第二个点爆搜+剪枝,我的剪枝就是先算出 \(mx[i]\) 表示选取第 \(i \ ...
- Loj #2731 「JOISC 2016 Day 1」棋盘游戏
Loj 2731 「JOISC 2016 Day 1」棋盘游戏 JOI 君有一个棋盘,棋盘上有 \(N\) 行 \(3\) 列 的格子.JOI 君有若干棋子,并想用它们来玩一个游戏.初始状态棋盘上至少 ...
随机推荐
- Java项目中常用的的五大设计原则
今天我们一起来聊聊关于设计原则相关的知识点. SOLID五大原则是什么 SRP 单一责任原则 单一责任原则,从名字上我们就能比较好的去理解它.这项原则主张一个对象只专注于单个方面的逻辑,强调了职责的专 ...
- 力扣 - 剑指 Offer 53 - I. 在排序数组中查找数字 I
题目 剑指 Offer 53 - I. 在排序数组中查找数字 I 思路1 一般来说,首先想到的是使用一个变量,从头开始遍历整个数组,记录target数组出现的次数,但是这样的时间复杂度是O(n),还是 ...
- rocketMQ(一)基础环境
一.安装: http://rocketmq.apache.org/dowloading/releases/ https://www.apache.org/dyn/closer.cgi?path=roc ...
- CanalAdmin搭建Canal Server集群
CanalAdmin搭建Canal Server集群 一.背景 二.机器情况 三.实现步骤 1.下载canal admin 2.配置canalAdmin 3.初始化canal admin数据库 4.启 ...
- 认识spring security
在一个系统中认证和授权是常有的事情,现在比较流行的框架有spring security.shiro等等.他们都能很好的帮助我们完成认证和授权的功能.那么假如说让我们自己完成一个登录那么应该大致的流程是 ...
- spring cloud config的使用
在传统的应用中,我们的配置文件都是放在项目中,这个影响不大.但是在一个微服务架构的系统中,我们的微服务可能存在几十上百个,并且每个小的微服务可能又部署在多台机器上,那么这个时候如果我们的配置文件在都放 ...
- eureka服务端和客户端的简单搭建
本篇博客简单记录一下,eureka 服务端和 客户端的简单搭建. 目标: 1.完成单机 eureka server 和 eureka client 的搭建. 2.完成eureka server 的添加 ...
- 算法:九宫格问题--奇数阶魔方(Magic-Square)
一.魔方介绍 魔方(这里是简称,也可以叫幻方.魔术矩阵,Magic Square)是 n×n 正方形网格(n 为每侧的单元数),里面每个单元格填充了不同的正整数 1, 2, 3, ... , n2,并 ...
- cf16C Monitor(额,,,,水数学,,)
题意: 一块镜子长宽是a*b.现在要调整(切割)成x:y的比例. 问调整完的最大面积是多少. 思路: 先将x,y弄成最简比例,然后放大到不超过min(a,b)即可. 代码: ll a,b,x,y; l ...
- 彻底解决SLF4J的日志冲突的问题
今天公司同事上线时发现,有的机器打印了日志,而有的机器则一条日志也没有打.以往都是没有问题的. 因此猜测是这次开发间接引入新的日志jar包,日志冲突导致未打印. 排查代码发现,系统使用的是SLF4J框 ...