cf 1073c 二分 思维

题意:给定一个长为n的串,代表机器人的行走方式,要求机器人到达(x,y)点

  将原串的子串修改,求最小的子串的长度

 

思路:

很容易知道如何到达x,y点    假设 res= abs(x)+abs(y);那么 n>=res && (n-res)%2==0

那么如何寻找一个子串呢?

二分枚举长度len,然后枚举所有长度为Len的子串看看有没有可能满足

   枚举子串已经用O(n)的复杂度了

    判断的条件就是剩余到达(nx,ny) 用长度为Len的子串是否能到(nx-x,ny-y)

   这样处理的话,处理前缀 就可以O(1)求Nx,ny了  

  总时间 n*logn

 

#include<bits/stdc++.h>
using namespace std;

#define ll long long
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define all(v) v.begin(),v.end()
#define pii pair<int,int>

const int N  =2e5+4;
const ll mod = 2e9+7;
const int INF = 1e9+3;
const ll LINF = 1e18+3;

int n; ll x,y;
int R[N],U[N];
char s[N];

bool can(int len){

    for(int i=1;i<=n-len+1;++i){

        int nx,ny;
        //[i,i+len-1]
        nx = R[i-1] + R[n]-R[i+len-1];
        ny = U[i-1] + U[n]-U[i+len-1];
        int need = abs(x-nx)+abs(y-ny);
        if(len>=need && (len-need)%2==0)return true;
    }
    return false;
}
int main(){


    cin>>n;
    scanf("%s",s+1);
    cin>>x>>y;

    for(int i=1;i<=n;++i){
        R[i]=R[i-1];U[i]=U[i-1];
        if(s[i]=='R')R[i]+=1;
        if(s[i]=='L')R[i]+=-1;
        if(s[i]=='U')U[i]+=1;
        if(s[i]=='D')U[i]+=-1;
    }
    int res= abs(x)+abs(y);
    if(n>=res && (n-res)%2==0){
        int l=0,r= n;
        int ans = n;
        while(l<=r){
            int mid =(l+r)/2;
            if(can(mid)){
                r = mid-1;
                ans = min(ans,mid);
            }
            else {
                l= mid+1;
            }
        }
        cout<<ans<<endl;
    }
    else {
        cout<<-1<<endl;
    }

    return 0;
}

 

转载于:https://www.cnblogs.com/wjhstudy/p/9856171.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值