P1686 挑战 题解

78km / 2023-07-31 / 原文

原题链接

题目大意

\(图上两个x或y值相同的点,如果其没有一条线段直接相连,则这两个点之间的距离为一条捷径\)
\(给定一条路径,求此路径上最短的捷径长度(注意,是捷径最短)以及捷径的起止点和方向\)

数据范围

\(1\le n\le 250000\)
\(先考虑x值相同的情况,假设有3个点A,B,C可以互相构成捷径\)
\(假设A_y>B_y>C_y,则捷径AC<捷径AB,且捷径AC<捷径BC\)
\(所以在x相同的时候,只需按照y值排序,即可使得最短捷径一定在相邻两点之间\)
\(于是可以O(n)求解\)
\(于是贪心方案即为,先把点按x排序,在x相同的时候按y排序\)\

bool cmp1(dian i,dian j)
{
	if(i.x==j.x)
	return i.y<j.y;
	return i.x<j.x;
}

\(可以使用这样的函数加上sort实现\)
\(再考虑y相同的点,其实和x值相同的情况类似,可以用同样方法求解\)
\(复杂度为排序复杂度\)
\(ps:此题要求在捷径长度相同时输出起点编号小的,如果起点编号也相同,则输出终点编号大的,坑死我了\)\

附AC代码
#include<bits/stdc++.h>
using namespace std;
int n,nowx,nowy,top;
struct dian
{
	int x,y,d;
}d[300009];
bool cmp1(dian i,dian j)
{
	if(i.x==j.x)
	return i.y<j.y;
	return i.x<j.x;
}
bool cmp2(dian i,dian j)
{
	if(i.y==j.y)
	return i.x<j.x;
	return i.y<j.y;
}
int len,l,r;
char fx;
int main()
{
	len=1e9;
	cin>>n;
	nowx=nowy=2500000;
	d[++top]={nowx,nowy,0};
	for(int i=1;i<=n;i++)
	{
		char a;
		cin>>a;
		if(a=='N')
		{
			nowy++;
			d[++top]={nowx,nowy,i};
		}
		if(a=='S')
		{
			nowy--;
			d[++top]={nowx,nowy,i};
		}
		if(a=='E')
		{
			nowx++;
			d[++top]={nowx,nowy,i};
		}
		if(a=='W')
		{
			nowx--;
			d[++top]={nowx,nowy,i};
		}
	}
	sort(d+1,d+top+1,cmp1);
	for(int i=2;i<=top;i++)
	{
		if(d[i].x!=d[i-1].x)
		continue;
		if(d[i].y-d[i-1].y<=len)
		{
			if(abs(d[i].d-d[i-1].d)<=1)
			continue;
			if(len==d[i].y-d[i-1].y)
			{
				int ll=d[i-1].d;
				int rr=d[i].d;
				if(ll>rr)
				swap(ll,rr);
				if(ll>l)
				continue;
				if(l==ll&&rr<r)
				continue;
				l=ll;
				r=rr;
				if(d[i].d>d[i-1].d)
				fx='N';
				else
				fx='S';
			}
			else
			{
				len=d[i].y-d[i-1].y;
				l=d[i-1].d;
				r=d[i].d;
				if(d[i].d>d[i-1].d)
				fx='N';
				else
				{
					swap(l,r);
					fx='S';
				}
			}
		}
	}
	sort(d+1,d+top+1,cmp2);
	for(int i=2;i<=top;i++)
	{
		if(d[i].y!=d[i-1].y)
		continue;
		if(d[i].x-d[i-1].x<=len)
		{
			if(abs(d[i].d-d[i-1].d)<=1)
			continue;
			if(len==d[i].x-d[i-1].x)
			{
				int ll=d[i-1].d;
				int rr=d[i].d;
				if(ll>rr)
				swap(ll,rr);
				if(ll>l)
				continue;
				if(l==ll&&rr<r)
				continue;
				l=ll;
				r=rr;
				if(d[i].d>d[i-1].d)
				fx='E';
				else
				fx='W';
			}
			else
			{
				len=d[i].x-d[i-1].x;
				l=d[i-1].d;
				r=d[i].d;
				if(d[i].d>d[i-1].d)
				fx='E';
				else
				{
					swap(l,r);
					fx='W';
				}
			}
		}
	}
	cout<<len<<' '<<l<<' '<<r<<' '<<fx;
	return 0;
}