Codeforces 1296C

题目大意:

给定一个机器人的行走方式

你需要取走一段区间

但要保证取走这段区间后机器人最终到达的终点位置是不变的

问这段区间最短时是哪一段

解题思路:

易得,如果重复走到了某些已经走过的点,那么肯定就有一段区间可以被删除

但是行走次数最大有2e5,即用数组记录坐标状态的话起码要开4e5*4e5的空间,显然不可能

所以可以用map储存上一次走到某个坐标是第几步

那么每次只要判断当前的坐标是否已经被走过即可,走过的话就尝试更新答案

因为map中未调用过的int值为0

所以让原点的步数设置为1防止混淆

初始设置 l=0,r=n+1去最大化这个答案区间,便于第一次判断得以执行

然后,遍历这个字符串,如果发现某个点已经走过了,取出这个步数为 d

可以得到 d+1~i 这一段是可以删除的(d步不可取,因为那一步走完才能到达这个点)

那么就拿 i-(d+1) 和 r-l 作比较,即当 r-l>i-(d+1)  =>  r-l>=i-d 时,更新lr答案

最后把第一步的步数减回去就可以作为答案了(l=0,说明不存在)

对于这里的结构体运算符重载,因为使用map需要告知大小关系才能存入这颗红黑树进行排序(map是会根据键值进行大小排序先的,然后进行二分查找)

所以就重载了小于运算符,先按照x从小到大排,如果x相同按照y从小到大排

这样就可以在之后二分查找时能够准确找到值

然后是对等于的重载,在查找的最后需要判断找到的位置的键值和输入的是否相同(因为如果找不到输入的键值的话是会返回空的——int类型即数值0)

所以要重载等于运算符

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
struct P{
    int x,y;
    bool operator < (const P& a) const{
        return x<a.x||x==a.x&&y<a.y;
    }
    bool operator == (const P& a) const{
        return x==a.x&&y==a.y;
    }
};
string s;
void solve(){
    int i,n,l,r,d;
    cin>>n>>s;
    map<P,int> mp;
    P pd;
    pd.x=pd.y=0;
    mp[pd]=1;
    l=0;r=n+1;//先最大化答案区间
    s="  "+s;//下标向右移动2位,便于直接把i当作步数
    for(i=2,n++;i<=n;i++){
        if(s[i]=='L')
            pd.x--;
        else if(s[i]=='R')
            pd.x++;
        else if(s[i]=='U')
            pd.y++;
        else
            pd.y--;
        d=mp[pd];
        if(d>0){//这个点走过
            if(r-l>=i-d)
                l=d+1,r=i;
        }
        mp[pd]=i;
    }
    if(l==0)
        cout<<"-1
";
    else
        cout<<l-1<<' '<<r-1<<'
';//因为原点步数为1,把差值减回去
}
int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    int T;cin>>T;while(T--)
        solve();
    
    return 0;
}
原文地址:https://www.cnblogs.com/stelayuri/p/12262316.html