C. Vasya and Robot (二分)

题目:传送门

题意:你起初在(0, 0), 你想去点 (x, y), 你有一个长度为 n 的运动字符串,字符串由 L,R,U,D 组成。问你你需要怎么改字符串,使得你跑完这个运动字符串之后,恰好在 (x, y) 且需 MaxID(你改动的那些字符的最大下标) - MinID(你改动的那些字符的最小下标) + 1 这个值最小, 输出这个最小值, 如果无论如何都到不了 (x, y) 输出 -1.

题解:二分需要改动的长度,改动的肯定是连续的 len 个字符,然后枚举改动的区间。对改动的区间外的执行操作,判断,所需步数和 len 的奇偶性是否相同且所需步数是否小于等于 len 。

#include <bits/stdc++.h>
#define LL long long
#define mem(i, j) memset(i, j, sizeof(i))
#define rep(i, j, k) for(int i = j; i <= k; i++)
#define dep(i, j, k) for(int i = k; i >= j; i--)
#define pb push_back
#define make make_pair
#define INF INT_MAX
#define inf LLONG_MAX
#define PI acos(-1)
using namespace std;

const int N = 1e6 + 5;

char a[N];
int n;
int x, y;

void update(pair <int, int>& Q, char s, int x) {
    if(s == 'U') Q.second += x;
    else if(s == 'D') Q.second -= x;
    else if(s == 'L') Q.first -= x;
    else if(s == 'R') Q.first += x;
}

bool judge(int len) {
    pair <int, int> tmp = make(0, 0);
    rep(i, len + 1, n) update(tmp, a[i], 1);

    int l = 1, r = len + 1;
    while(1) {
        int now = abs(x - tmp.first) + abs(y - tmp.second);
        if((now % 2) == (len % 2) && len >= now) return true;
        if(r == n + 1) break;
        update(tmp, a[l++], 1);
        update(tmp, a[r++], -1);
    }
    return false;
}

void solve() {
    scanf("%d", &n);
    scanf("%s", a + 1);
    scanf("%d %d", &x, &y);if(!judge(n)) { puts("-1"); return ; }
    int l = -1, r = n;
    while(r - l > 1) {
        int mid = (l + r) / 2;
        if(judge(mid)) r = mid;
        else l = mid;
    }
    printf("%d\n", r);
    return ;
}

int main() {

    solve();

    return 0;
}

猜你喜欢

转载自www.cnblogs.com/Willems/p/12388568.html