正题

题目链接:https://loj.ac/p/2769


题目大意

给出\(n\)个点\(m\)条地铁线路,每条线路是一条路径。

求\(1\)到\(n\)的最短路且在最短路径的情况下相邻换乘点的距离平方和最大。

\(1\leq n,m,\sum s_i\leq 10^6\)


解题思路

首先肯定是在最短路树上跑,然后考虑怎么求平方和最大。

因为每条可以计算和的路径一定是连续的一段,所以考虑将一条铁路线去掉不在最短路树上的边后分出若干段来。

对于每一段上的转移都是一个\(f_{x}=max\{f_y+(d_x-d_y)^2\}\)的形式,可以斜率优化。

但是为了充分转移,需要按照\(dis\)从小到大转移。

栈啊什么的开\(vector\)就好了。

时间复杂度\(O(n\log n)\)


code

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<queue>
#include<cctype>
#define mp(x,y) make_pair(x,y)
#define sec second
#define fir first
#define ll long long
using namespace std;
const ll N=1e6+10;
struct node{
ll to,next,w;
}a[N];
ll n,m,T,tot,ls[N],dis[N],f[N],top[N],p[N],las[N];
vector<pair<ll,ll> >e[N],E[N],pos[N];
priority_queue<pair<ll,ll> >q;
vector<ll> _x[N],_y[N],s[N];bool v[N];
ll read(){
ll x=0,f=1;char c=getchar();
while(!isdigit(c)){if(c=='-')f=-f;c=getchar();}
while(isdigit(c)){x=(x<<1)+(x<<3)+c-48;c=getchar();}
return x*f;
}
void addl(ll x,ll y,ll w){
a[++tot].to=y;
a[tot].next=ls[x];
ls[x]=tot;a[tot].w=w;
return;
}
void dij(){
memset(dis,0x3f,sizeof(dis));
q.push(mp(0,1));dis[1]=0;
while(!q.empty()){
ll x=q.top().sec;q.pop();
if(v[x])continue;v[x]=1;
for(ll i=ls[x];i;i=a[i].next){
ll y=a[i].to;
if(dis[x]+a[i].w<dis[y]){
dis[y]=dis[x]+a[i].w;
q.push(mp(-dis[y],y));
}
}
}
return;
}
bool cmp(ll x,ll y)
{return dis[x]<dis[y];}
double slope(ll x,ll y,ll p)
{return (double)(_y[p][y]-_y[p][x])/(_x[p][y]-_x[p][x]);}
void calc(ll x,ll p,ll t,vector<ll> &s,ll &top){
//x点 p线 t站
if(!t)return;
ll dx=e[p][t].sec;
while(top>1&&slope(s[top-1],s[top],p)<=2*dx)top--;
if(top){
ll y=s[top];
f[x]=max(f[x],_y[p][y]-2*dx*_x[p][y]+dx*dx);
}
}
void add(ll x,ll p,ll t,vector<ll> &s,ll &top){
//x点 p线 t站
if(t>=e[p].size()-1)return;
ll dx=e[p][t].sec;
_y[p][t]=f[x]+dx*dx;_x[p][t]=dx;
while(top>1&&slope(s[top-1],t,p)>=slope(s[top-1],s[top],p))top--;
s[++top]=t;las[p]=t;return;
}
signed main()
{
// freopen("city.in","r",stdin);
// freopen("city.out","w",stdout);
n=read();m=read();
for(ll i=1;i<=m;i++){
ll num,x,t=0;num=read()+1;
while(num--){
if(E[i].size())t=read();x=read();
if(E[i].size()){
pair<ll,ll> z=E[i][E[i].size()-1];
addl(z.fir,x,t);
}//建边
E[i].push_back(mp(x,t));
}
}
dij();
for(int i=1;i<=m;i++){
for(int j=0;j<E[i].size();j++){
int x=E[i][j].first,t=E[i][j].sec,flag=1;
if((!j)||dis[E[i][j-1].fir]+E[i][j].sec!=dis[E[i][j].fir]){
if(T&&e[T].size()==1){
pos[e[T][0].first].pop_back();
e[T][0].first=x;
flag=0;
}
else T++,e[T].push_back(mp(x,0));
}
else e[T].push_back(mp(x,t));
if(flag)s[T].push_back(0),_x[T].push_back(0),_y[T].push_back(0);
pos[x].push_back(mp(T,e[T].size()-1));
//e:线路(点/和前面的长度)
//pos:点(线路,对应位置)
//s,_x,_y:dp用数组
}
}
for(ll i=1;i<=T;i++)
for(ll j=1;j<e[i].size();j++)
e[i][j].sec+=e[i][j-1].sec;
for(ll i=1;i<=n;i++)p[i]=i;
sort(p+1,p+1+n,cmp);
for(ll _i=1;_i<=n;_i++){
ll x=p[_i];
for(ll _j=0;_j<pos[x].size();_j++)
calc(x,pos[x][_j].fir,pos[x][_j].sec,s[pos[x][_j].fir],top[pos[x][_j].fir]);
for(ll _j=0;_j<pos[x].size();_j++)
add(x,pos[x][_j].fir,pos[x][_j].sec,s[pos[x][_j].fir],top[pos[x][_j].fir]);
if(x==n)break;
}
printf("%lld %lld\n",dis[n],f[n]);
return 0;
}

Loj#2769-「ROI 2017 Day 1」前往大都会【最短路树,斜率优化】的更多相关文章

  1. LOJ #2769 -「ROI 2017 Day 1」前往大都会(单调栈维护斜率优化)

    LOJ 题面传送门 orz 斜率优化-- 模拟赛时被这题送走了,所以来写篇题解( 首先这个最短路的求法是 trivial 的,直接一遍 dijkstra 即可( 重点在于怎样求第二问.注意到这个第二问 ...

  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. uwp 自定义语音识别规则

    xml  code ---------------------------------------------------- <Page x:Class="MyApp.MainPage ...

  2. C# 委托讲解

    首先,委托的使用场景:A的某些功能,只有在B需要触发时触发,委托就是用来做中间通讯的渠道. 假设:现在有个大佬A,A有个小弟B,B在受到羞辱时就会通过电话Delegate通知A自己被羞辱了,A在这时就 ...

  3. Linux操作系统基本应用(完结)

      时间:2015-4-10 12:40Linux第一天 Linux基本命令  Linux各文件夹的作用    bin  二进制可执行命令    dev  设备特殊文件    etc  系统管理和配置 ...

  4. Python 3.10 is coming!

    看看Python 官网的文档 whatsnew,Python 3.10 已然距离我们越来越近了,然我们看看 Python 3.10 相较于 Python 3.9 有哪些改变吧 新特性 通过括号来组织多 ...

  5. java 查询当天0点0分0秒

    由于业务需求,要计算客户今日收益,本周本月,本年等收益, 1.查询当天0点0分0秒 2.查询本月一号0点0分0秒 ...... Calendar calendar = Calendar.getInst ...

  6. linux centos7 tail

    2021-08-30 # 不指定行数,默认显示 10 行 # 显示 /var/log/crond 后100行 taile -100 /var/log/crond # 动态显示 /var/log/cro ...

  7. win10画板超实用的快捷键

    win10画板超实用的快捷键链接: Windows 7 画图中的快捷键 Windows中画图的快捷键 其中有windows默认的快捷键,关于画图工具加入到快捷工具也有详细的介绍.

  8. Python习题集(九)

    每天一习题,提升Python不是问题!!有更简洁的写法请评论告知我! https://www.cnblogs.com/poloyy/category/1676599.html 题目 已知一个数列:1. ...

  9. adb 常用命令大全(5)- 日志相关

    前言 Android 系统的日志分为两部分 底层的 Linux 内核日志输出到 /proc/kmsg Android 的日志输出到 /dev/log 语法格式 adb logcat [<opti ...

  10. 关于Golang的学习路线

    基础 安装golang环境 Golang基础,流程控制,函数,方法,面向对象 网络编程(自己做一个简单的tcp的聊天室,websocket,http,命令行工具) 并发(可以看一下并发爬虫或者下载器的 ...