CF1422D Returning Home - the shortest path + greedy connection

Topic

CodeForces - 1422D 

answer

About the topic translation, go to Baidu, you can understand it.

Read the question first: "instant-movement locations" (IML for short) are used to summon you from the same row or column to this position in an instant (ie, zero time).

Consider the shortest path between the start point, the end point and each IML. Due to the special nature of IML, the distance between any point and one IML is the minimum value of the difference between the x coordinate and the y coordinate;

Since you can reach a certain IML from the same row or column instantly, but you cannot reach a certain position in the same row or column from a certain IML position, you have to treat it as a common point when connecting from the IML.

Yes O (m ^ 2), time and space will explode;

Consider the following situation:

If you connect them with edges, the distance from a to c is y_a-y_c, but if you only connect ab and bc, the distance from a to c is still y_a-y_b + y_b-y_c = y_a-y_c,

So we only need to connect the point with the y-coordinate closest to it above or below each IML. The same goes for the horizontal direction, and only the two points with the closest x-coordinate are connected.

In this way, 4m edges are connected at most, Dij is optimized for heap O ((m + 4m) log (4m)), and line segment tree is optimizedO((m+4m)logm)

Code

I use Dij optimized by the line segment tree. In fact, you don’t need to...

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<queue>
#include<vector>
#define ll long long
#define MAXN 100005
#define MOD 998344353ll
using namespace std;
inline ll read(){
	ll x=0;bool f=1;char s=getchar();
	while((s<'0'||s>'9')&&s>0){if(s=='-')f^=1;s=getchar();}
	while(s>='0'&&s<='9')x=(x<<1)+(x<<3)+s-'0',s=getchar();
	return f?x:-x;
}
int n,m,f[MAXN*3],p,st[MAXN];
bool vis[MAXN];
ll d[MAXN];

struct P{ll x,y;}s[MAXN];
struct itn{
	int v;ll w;
	itn(){}
	itn(int V,ll W){v=V,w=W;}
};
inline bool cmp(P a,P b){
	if(a.x!=b.x)return a.x<b.x;
	else return a.y<b.y;
}
inline bool cmp_(int a,int b){return s[a].y<s[b].y;}
vector<itn>G[MAXN];

inline ll ads(ll x){return x>0?x:-x;}
inline ll getd(P a,P b){return min(ads(a.x-b.x),ads(a.y-b.y));}
inline ll getd_(P a,P b){return ads(a.x-b.x)+ads(a.y-b.y);}
inline int MIN(int a,int b){return d[a]<d[b]?a:b;}

inline void change(int x,int d){//四行zkw
	for(f[p+x]=d,x=(x+p)>>1;x>0;x>>=1)
		f[x]=MIN(f[x<<1],f[x<<1|1]);
}

int main()
{
	n=read(),m=read();
	s[0].x=read(),s[0].y=read(),s[m+1].x=read(),s[m+1].y=read();
	for(int i=1;i<=m;i++)s[i].x=read(),s[i].y=read();
	sort(s+1,s+1+m,cmp);
	for(int i=1;i<=m;i++)st[i]=i;
	sort(st+1,st+1+m,cmp_);
	G[0].push_back(itn(m+1,getd_(s[0],s[m+1])));
	for(int i=1;i<m;i++){
		G[i].push_back(itn(i+1,getd(s[i],s[i+1])));
		G[i+1].push_back(itn(i,getd(s[i],s[i+1])));
	}
	for(int i=1;i<m;i++){
		G[st[i]].push_back(itn(st[i+1],getd(s[st[i]],s[st[i+1]])));
		G[st[i+1]].push_back(itn(st[i],getd(s[st[i]],s[st[i+1]])));
	}
	for(int i=1;i<=m;i++){
		G[0].push_back(itn(i,getd(s[0],s[i])));
		G[i].push_back(itn(m+1,getd_(s[i],s[m+1])));
	}
	memset(d,0x7f,sizeof(d));
	for(p=1;p<m+3;p<<=1);
	for(int i=0;i<G[0].size();i++){
		int v=G[0][i].v;ll w=G[0][i].w;
		d[v]=min(d[v],w),change(v,v);
	}
	for(int T=1;T<=m;T++){
		int u=f[1];//不用查询,直接问祖
		if(u==0)break;
		change(u,0),vis[u]=1;
		for(int i=0;i<G[u].size();i++)
			if(!vis[G[u][i].v]){
				int v=G[u][i].v;ll w=G[u][i].w;
				d[v]=min(d[v],d[u]+w),change(v,v);
			}
	}
	printf("%lld\n",d[m+1]);
	return 0;
}

 

Guess you like

Origin blog.csdn.net/weixin_43960287/article/details/110655019