首页 > 其他分享 >CF1715E Long Way Home题解

CF1715E Long Way Home题解

时间:2024-02-11 21:12:09浏览次数:32  
标签:le int 题解 pos check Way Home mx dp

题解

注意到 \(k\) 是一个很小的数,我们考虑分层图是否可做,这时航线有 \(n^2\) 条,我们可能会建出 \((k+1)m+kn^2\) 条边,空间会炸掉,然而单单从分层图的角度来优化,是困难的。

对于 \(m=0\) 的情况。考虑 \(\text{dp}\),定义 \(dp_{i,j}\) 表示乘坐不超过 \(i\) 次航班到达 \(j\) 的最小花费。那么有如下转移方程:

\[dp_{i,j}=\min({\min_{1 \le t \le n}{dp_{i-1,t}+(j-t)^2}},dp_{i-1,j}) \]

暴力递推的复杂度是 \(O(kn^2)\) 的,炸了。我们转化一下 \(\text{DP}\) 的转移方程:

\[dp_{i,j}=\min({\min_{1 \le t \le n}(-2jt+dp_{i-1,t}+t^2)+j^2},dp_{i-1,j}) \]

我们定义出 \(n\) 条线段,对于第 \(i\) 条线段,其解析式为:

\[y=-2tx+dp_{i-1,t}+t^2(1\le x \le n) \]

那么我们就是要求直线 \(x=j\) 与这 \(n\) 条线段的交点中纵坐标的最小值,可使用李超线段树维护,注意到,由于插入的线段的定义域都是相同的,我们没有拆分区间的必要,于是插入一条线段的复杂度是 \(O(\log n)\) 的,总复杂度为 \(O(kn\log n)\)。

对于 \(m>0\) 的情况。保持 \(dp_{i,j}\) 的定义不变,那么在做完上述转移之后,我们还有如下转移式:

\[dp_{i,j}=\min_{(t,j)\in E}dp_{i,t}+w(t,j) \]

其中 \(E\) 是原图边集,这里无后效性不能保证,但是显然可用 \(\text{Dijkstra}\) 算法更新。这一部分的时间复杂度仍然是 \(O(kn\log n)\)。那么,我们就在 \(O(kn\log n)\) 的时间内解决了问题。

代码实现上,要注意的是:1.转移的第一维只涉及两个阶段,可用滚动数组减小空间常数。2.在用 \(\text{Dijkstra}\) 算法更新时,\(dp_{i,j}\) 是有初值的,可以看作有一条边 \((1,j,dp_{i,j})\),所以要先把这 \(n\) 条边入队。3.对于 \(dp_{0,j}\),这个相当于原图最短路,还是有意义的,要求解。

AC code

点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=2e5+10;
const int inf=1e15;
int n,m,k;
int ver[N],edge[N],head[N],Next[N],d[N],D[N],vis[N],tot,u,v,w;
int rt,sz,ans;
priority_queue<pair<int,int> >q;
struct Line {
	int k,b;
}a[N];
struct node {
	int ls,rs,mx;
}t[N<<2];
bool check(int i,int j,int x) {
	if(a[i].k*x+a[i].b-a[j].k*x-a[j].b>0) return false;
	return true;
}
void Insert(int &p,int L,int R,int pos) {
	if(!p) p=++sz;
	if(check(pos,t[p].mx,L)&&check(pos,t[p].mx,R)) {
		t[p].mx=pos;
		return;
	}
	if(!check(pos,t[p].mx,L)&&!check(pos,t[p].mx,R)) return;
	int mid=L+R>>1;
	if(check(pos,t[p].mx,mid)) swap(pos,t[p].mx);
	if(check(pos,t[p].mx,L)) Insert(t[p].ls,L,mid,pos);
	if(check(pos,t[p].mx,R)) Insert(t[p].rs,mid+1,R,pos);
}
void query(int p,int L,int R,int x) {
	if(!p) return;
	if(check(t[p].mx,ans,x)) ans=t[p].mx;
	if(L==R) return;
	int mid=L+R>>1;
	if(x<=mid) query(t[p].ls,L,mid,x);
	else query(t[p].rs,mid+1,R,x);
}
void add(int x,int y,int z) {
	ver[++tot]=y;
	edge[tot]=z;
	Next[tot]=head[x];
	head[x]=tot;
}
void dijkstra() {
	for(int i=1;i<=n;i++) {
		vis[i]=0;
		q.push(make_pair(-d[i],i));
	}
	while(!q.empty()) {
		int x=q.top().second;
		q.pop();
		if(vis[x]) continue;
		vis[x]=1;
		for(int i=head[x];i;i=Next[i]) {
			int y=ver[i],z=edge[i];
			if(d[y]>d[x]+z) {
				d[y]=d[x]+z;
				q.push(make_pair(-d[y],y));
			}
		}
	}
}
signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	cin>>n>>m>>k;
	for(int i=1;i<=m;i++) {
		cin>>u>>v>>w;
		add(u,v,w);
		add(v,u,w);
	}
	for(int i=1;i<=n;i++) d[i]=inf;
	d[1]=0;
	dijkstra();
	a[0].k=0,a[0].b=inf;
	for(int i=1;i<=k;i++) {
		for(int j=1;j<=n;j++) {
			a[j].k=-2*j,a[j].b=d[j]+j*j;
			Insert(rt,1,n,j);
		}
		for(int j=1;j<=n;j++) {
			ans=0;
			query(rt,1,n,j);
			D[j]=min(d[j],-2*ans*j+d[ans]+ans*ans+j*j);
		}
		for(int j=1;j<=n;j++) d[j]=D[j];
		dijkstra();
	}
	for(int i=1;i<=n;i++) cout<<d[i]<<" ";
	return 0;
}

标签:le,int,题解,pos,check,Way,Home,mx,dp
From: https://www.cnblogs.com/2021hych/p/18013530

相关文章

  • CF1928E 题解
    \(\textbf{ProblemStatement}\)给定\(n,x,y,s\),构造长度为\(n\)的序列\(a\),满足:\(a_1=x\)。\(\foralli\in[2,n],a_i=a_{i-1}+y\)或者\(a_i=a_{i-1}\bmody\)。\(\sum\limits_{i=1}^na_i=s\)。给出构造或报告无解。\(\sumn,\sums\le......
  • 题解 AT_mujin_pc_2016_c【オレンジグラフ】
    本文中点的编号从\(0\)开始。显然,题目中要求橙色的边构成极大的二分图。枚举二分图左右部分别有哪些点。特别地,钦定\(0\)号点是左部点。将所有跨左右部的边染为橙色,如果所有点通过橙色的边连通,就得到了一组合法的解;如果不连通,显然可以将更多的边染成橙色,使得所有点连通。//......
  • 题解 ABC336G【16 Integers】
    萌萌BEST定理练习题。赛时几乎做出来了,但写挂了,现在在火车上没事干就给补了。考虑建图,图中共有\(8\)个节点,节点的编号是\((\mathbb{Z}/2\mathbb{Z})^3\)的每个元素。对于每个四元组\((i,j,k,l)\in(\mathbb{Z}/2\mathbb{Z})^4\),在图中连\(X_{i,j,k,l}\)条\((i,j,k)\to(j......
  • 抛弃Spring Cloud Gateway,得物 使用Netty架构100Wqps网关
    文章很长,且持续更新,建议收藏起来,慢慢读!疯狂创客圈总目录博客园版为您奉上珍贵的学习资源:免费赠送:《尼恩Java面试宝典》持续更新+史上最全+面试必备2000页+面试必备+大厂必备+涨薪必备免费赠送:《尼恩技术圣经+高并发系列PDF》,帮你实现技术自由,完成职业升级,薪......
  • 洛谷 P1795 无穷的序列 题解
    题目传送门题目大意:给定整数\(a\),判断\(a\)是否属于数列\(1,2,4,7,11\cdots\)。多测。1.暴力枚举(90pts)不难发现,该数列除第一项外第\(n\)项比第\(n-1\)项多\(n-1\)。故暴力枚举\(n\),计算数列的每一项,判断是否与\(a\)相等,大于\(a\)就break。多测加记忆化,用mx......
  • link标签中的rel="home"表示什么意思?
    rel属性用于指定链接的关系。例如:<linkrel="home"title="home"href="https://emuchong.com/"/>用以表示当前网页的主页是https://emuchong.com/这个地址。这样做的好处除了提供语义的基本描述,Opera会自动识别出文档<head>段中<link>的rel-home属性。Opera浏览器会提供一个......
  • P5524 [Ynoi2012] NOIP2015 充满了希望 题解
    题目链接:充满了希望一开始以为是传统老题,结果看到有个交换单修操作,ODT这题试了下,应该\(fake\)了,毕竟有单修,很难保证之前的\(log\)级复杂度。有些较为智慧的解法确实不好思考,说个很简单的做法,这里没有问颜色数,而是问的颜色具体情况,那就比之前的很多题简单太多了。颜色的具体......
  • AtCoder-abc340_f题解
    题意简述给定整数\(x,y\),询问是否存在整数\(a,b\),满足:\(-10^{18}\lea,b\le10^{18}\)。由\((0,0),(x,y),(a,b)\)三点构成的三角形面积为\(1\)。如果存在,输出任意一组;否则输出-1。思路先假设\(x,y,a,b\)都是正数。那么图大概是这样:此时红色三角形的面积就......
  • P4183 [USACO18JAN] Cow at Large P 题解
    Description贝茜被农民们逼进了一个偏僻的农场。农场可视为一棵有\(N\)个结点的树,结点分别编号为\(1,2,\ldots,N\)。每个叶子结点都是出入口。开始时,每个出入口都可以放一个农民(也可以不放)。每个时刻,贝茜和农民都可以移动到相邻的一个结点。如果某一时刻农民与贝茜相遇了......
  • [AGC062B] Split and Insert 题解
    题目链接点击打开链接题目解法咋神仙区间\(dp\)题永远想不到区间\(dp\)???首先把操作顺序反转那么现在的问题就是:每次可以选出一个子序列放到序列末尾,使序列升序的最小代价这个问题看着也是毫无头绪我尝试去找些规律,当然也没找到考虑精细刻画操作过程:最终的序列是升序的,最......