又是废掉的一个div2啊

第一次在学校熬夜打cf,开心还看到了自己最喜欢的斜率优化ohhh

链接 :E - Long Way Home

看到那个平方就可以靠感觉认为是斜率优化了....

感觉似不似有点想法??k只有20...

可以试着去考虑最后一步用飞机,然后跑dijkstra求出走普通路径的。

其实就这样了...


考虑k=1的情况:

在最后坐飞机,前面都普通路径行走

则:\(d_{new}[i]=min(d_{old}[j]+(i-j)^2)\)

\(d_{new}\)为最后的答案,就是在最后坐飞机,\(d_{old}\)就是前面已经处理的走普通路径

然后跑一遍dijkstra,看看是否会更新(即假设存在A->C的最短路径为:A->B最后坐飞机,B->C走普通路径)


处理k>1的情况也是一样的,做k次dp,每一次在dp后跑最短路看能否用普通路径更新。

注意的是在一开始要跑一遍最短路,代表坐0次飞机的最短路径。

然后就是对于这个dp式子的处理了:

观察发现可以把式子转换为:\(d_{old}[j]+j^2=2ij+d_{new}[i]-i^2\)

斜率为\(2i\),X为\(j\),Y为\(d_{old}[j]+j^2\)。斜率和X都单调递增,所以可以画图发现决策点是下凸(为什么不转换式子要画图?因为j有特殊的点)

这个j特殊的点就在于没有范围的限制,也就是范围是(1<=j<=n)

所以就不可以在循环中加入单调队列

可以先一遍循环把所有决策点存入单调队列,然后再一遍循环更新答案

就完了....

对了!还有一个点:因为m可能小于n,图可能不连通,也就是说从只1号点跑dijkstra就不一定可以遍历完,所以就需要在dp时如果更新了\(d_{new}\)就要把它放入优先队列中,以保证每个点都可以更新到。

Over.

一定要在计算Y的时候把\(j^2\)开成long long啊!!!麻了,改了一个小时(ku)

总的复杂度\(O(k(mlogn+n))\)

代码:

#include<bits/stdc++.h>
#define ll long long
using namespace std;
inline int read(){
register int x = 0, t = 1;
register char ch=getchar();
while(ch<'0'||ch>'9'){
if(ch=='-')
t=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9'){
x=(x<<1)+(x<<3)+(ch^48);
ch=getchar();
}
return x*t;
}
struct node{
int to,nxt,w;
}e[200010];
int head[100010],cnt,vis[100010];
void add(int u,int v,int w){
e[++cnt].to=v;
e[cnt].nxt=head[u];
e[cnt].w=w;
head[u]=cnt;
}
ll dist[100010],dis[110000]/*old*/;
struct h{
int id;
ll dis;
bool operator<(const h &other)const{
return dis>other.dis;
}
};
priority_queue<h>qu;
void dijkstra(){//更新以普通边结尾
memset(vis,0,sizeof(vis));
qu.push((h){1,0});
while(!qu.empty()){
int p=qu.top().id;
qu.pop();
if(vis[p])continue;
vis[p]=1;
for(int i=head[p];i;i=e[i].nxt){
int v=e[i].to;
if(dist[v]>dist[p]+e[i].w){
dist[v]=dist[p]+e[i].w;
qu.push((h){v,dist[v]});
}
}
}
}
int q[100010],hd,tl;
ll Y(int i){return dis[i]+(ll)i*i;/*爆了!!*/}
ll X(int i){return i;}
ll K(int i){return 2*i;}
double slope(int x,int y){//x>y
if(X(x)==X(y)){
if(Y(x)<Y(y))return -1e18;
else return 1e18;
}
return (double)(Y(x)-Y(y))/(X(x)-X(y));
}
int main(){
int n=read(),m=read(),k=read();
for(int i=1;i<=m;i++){
int x=read(),y=read(),w=read();
add(x,y,w),add(y,x,w);
}
for(int i=2;i<=n;i++)dist[i]=1e18;
dijkstra();
while(k--){
for(int i=1;i<=n;i++)dis[i]=dist[i];
hd=tl=0;
for(int i=1;i<=n;i++){
//下凸壳
while(hd+1<tl&&slope(i,q[tl-1])<=slope(q[tl-1],q[tl-2]))tl--;
q[tl++]=i;
}
for(int i=1;i<=n;i++){
while(hd+1<tl&&slope(q[hd+1],q[hd])<=K(i))hd++;
if(hd<tl){
int j=q[hd];
if(dist[i]>dis[j]+(ll)(j-i)*(j-i)){
dist[i]=dis[j]+(ll)(j-i)*(j-i);
qu.push((h){i,dist[i]});
}
}
}
dijkstra();
}
for(int i=1;i<=n;i++)printf("%lld ",dist[i]);
return 0;
}

Codeforces 1715E - Long Way Home的更多相关文章

  1. python爬虫学习(5) —— 扒一下codeforces题面

    上一次我们拿学校的URP做了个小小的demo.... 其实我们还可以把每个学生的证件照爬下来做成一个证件照校花校草评比 另外也可以写一个物理实验自动选课... 但是出于多种原因,,还是绕开这些敏感话题 ...

  2. 【Codeforces 738D】Sea Battle(贪心)

    http://codeforces.com/contest/738/problem/D Galya is playing one-dimensional Sea Battle on a 1 × n g ...

  3. 【Codeforces 738C】Road to Cinema

    http://codeforces.com/contest/738/problem/C Vasya is currently at a car rental service, and he wants ...

  4. 【Codeforces 738A】Interview with Oleg

    http://codeforces.com/contest/738/problem/A Polycarp has interviewed Oleg and has written the interv ...

  5. CodeForces - 662A Gambling Nim

    http://codeforces.com/problemset/problem/662/A 题目大意: 给定n(n <= 500000)张卡片,每张卡片的两个面都写有数字,每个面都有0.5的概 ...

  6. CodeForces - 274B Zero Tree

    http://codeforces.com/problemset/problem/274/B 题目大意: 给定你一颗树,每个点上有权值. 现在你每次取出这颗树的一颗子树(即点集和边集均是原图的子集的连 ...

  7. CodeForces - 261B Maxim and Restaurant

    http://codeforces.com/problemset/problem/261/B 题目大意:给定n个数a1-an(n<=50,ai<=50),随机打乱后,记Si=a1+a2+a ...

  8. CodeForces - 696B Puzzles

    http://codeforces.com/problemset/problem/696/B 题目大意: 这是一颗有n个点的树,你从根开始游走,每当你第一次到达一个点时,把这个点的权记为(你已经到过不 ...

  9. CodeForces - 148D Bag of mice

    http://codeforces.com/problemset/problem/148/D 题目大意: 原来袋子里有w只白鼠和b只黑鼠 龙和王妃轮流从袋子里抓老鼠.谁先抓到白色老鼠谁就赢. 王妃每次 ...

随机推荐

  1. 用Arduino玩GM65二维码扫描模块

    目录 用Arduino玩GM65二维码扫描模块 用Arduino玩GM65二维码扫描模块 最近在做Capstone,内容是我们之前实验室参加过的工程训练的物流搬运小车,所以现在来复盘一下我使用Ardu ...

  2. .NET C#基础(4):属性 - 本质是方法

    0. 文章目的   本文面向有一定.NET C#基础知识的学习者,介绍C#中属性的属性.定义.使用方法以及特殊性. 1. 阅读基础   理解C#基本语法(定义类及类成员,调用方法)   认可OOP的封 ...

  3. ER图/模型转换为关系模型

    ER图中的主要成分是实体类型和联系类型,转换规则就是如何把实体类型.联系类型转换成关系模式. 1. 二元联系转换 规则1.1(实体类型的转换):将每个实体类型转换成一个关系模式,实体的属性即为关系模式 ...

  4. 使用kubeseal加密和管理k8s集群的secret

    使用kubeseal加密和管理k8s集群的secret 在k8s的管理过程中,像secret这种资源并不好维护,kubeseal提供了一种相对简单的方式来对原始secret资源进行加密,并通过控制器进 ...

  5. 2 万字 + 30 张图 | 细聊 MySQL undo log、redo log、binlog 有什么用?

    作者:小林coding 计算机八股文网站:https://xiaolincoding.com/ 大家好,我是小林. 从这篇「执行一条 SQL 查询语句,期间发生了什么?」中,我们知道了一条查询语句经历 ...

  6. BUUCTF-爱因斯坦

    爱因斯坦 16进制打开可以看到存在压缩包,使用binwalk分离出来 提示需要解压密码,按照常理爆破四位数纯数字没有出来,查看图片属性发现密码 得到flag

  7. Web思维导图实现的技术点分析(附完整源码)

    简介 思维导图是一种常见的表达发散性思维的有效工具,市面上有非常多的工具可以用来画思维导图,有免费的也有收费的,此外也有一些可以用来帮助快速实现的JavaScript类库,如:jsMind.KityM ...

  8. Python教程:执行cmd命令

    我们通常可以使用os模块的命令进行执行cmd 方法一:os.system def system(*args, **kwargs): # real signature unknown "&qu ...

  9. Java 图片生成PDF

    public static void main(String[] args) { String imageFolderPath = "E:\\Tencet\\图片\\test\\" ...

  10. Redis如何实现多可用区?

    在如今的业务场景下,高可用性要求越来越高,核心业务跨可用区已然成为标配.腾讯云数据库高级工程师刘家文结合腾讯云数据库的内核实战经验,给大家分享Redis是如何实现多可用区,内容包含Redis主从版.集 ...