题目:传送门
题意:你起初在(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; }