洛谷 P1686 挑战 题解
洛谷 P1686 挑战 题解
题目链接
思路分析
由于捷径只能是水平或竖直,即 \(x\) 相同或 \(y\) 相同,故我们可以对每一个 \(x\) 和每一个 \(y\) 单独考虑。具体地,在一个相同的 \(x\) 上找到两端点编号不连续的长度最小的线段即可。但是,这样剥离的做法实现较为繁琐,考虑重新分类。观察到每条线段有固定的端点,故枚举每个点,查找嵌套 map 找出最近的 \(x\) 相同或 \(y\) 相同的点。使用 unordered_map<int,map<int,int>> 记录每一个 \(x\) 中每一个 \(y\) 对应的坐标的最大编号(由于题中要求末端编号尽可能大)和每一个 \(y\) 中每一个 \(x\) 对应的坐标的最大编号即可。
代码呈现
写代码时,注意边界问题,判断当前是否为内层 map 的边界。
#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> pii;
struct node{
int u,v,w;
char d;
bool operator< (const node &_t) const{ // 重载小于号,注意 const
if (w==_t.w){
if (u==_t.u) return v>_t.v;
return u<_t.u;
}
return w<_t.w;
}
};
const int N=2.5e5+10;
int n;
int a[N],b[N];
char s[N];
map<pii,int> mp;
unordered_map<int,map<int,int>> X,Y;
inline int abs(int x){ return x<0?-x:x; }
int main(){
scanf("%d%s",&n,s+1);
for (int i=1,x=0,y=0;i<=n;++i){
if (s[i]=='N') ++y;
else if (s[i]=='S') --y;
else if (s[i]=='E') ++x;
else --x;
a[i]=x,b[i]=y,X[x][y]=Y[y][x]=i;
}
node s={INT_MAX,INT_MIN,INT_MAX,0};
for (int i=1;i<=n;++i){
auto p1=X[a[i]].find(b[i]),q1=Y[b[i]].find(a[i]),p2=p1,q2=q1;
if (p1!=X[a[i]].begin() && abs((--p1)->second-i)!=1) // 注意判断非相邻节点
s=min(s,{i,p1->second,b[i]-p1->first,'S'});
if (++p2!=X[a[i]].end() && abs(p2->second-i)!=1)
s=min(s,{i,p2->second,p2->first-b[i],'N'});
if (q1!=Y[b[i]].begin() && abs((--q1)->second-i)!=1)
s=min(s,{i,q1->second,a[i]-q1->first,'W'});
if (++q2!=Y[b[i]].end() && abs(q2->second-i)!=1)
s=min(s,{i,q2->second,q2->first-a[i],'E'});
}
printf("%d %d %d %c",s.w,s.u,s.v,s.d);
return 0;
}

浙公网安备 33010602011771号