题意:
给定长度为n的字符串,每个字符表示朝上下左右四个方向前进,给定一个目标位置,找一个最小的区间,使得改变这个区间的若干个字符,使得整个串的操作能到达目标位置只需要输出最小区间长度
思路:
首先暴力的想法就是枚举所有的区间,这样这个区间两边就会有一些操作不会改变,然后我们根据这些操作得到一个位置,跟目标位置比较,看看我们能否通过设置这个区间达到目标位置,显然复杂度很高;
然后就可以想到二分,二分区间长度,然后对于当前区间长度,枚举开始位置,检查是否可以到达目标位置,这样的话还是按照上述暴力的思路,我们得知道不改变的操作能到达的位置,这就需要我们预处理前缀和后缀能对上下左右四个方向做出的贡献,可以得到一个“位置”,然后检查是否可行
#include<bits/stdc++.h>
using namespace std;
#define out fflush(stdout)
#define fast ios::sync_with_stdio(0),cin.tie(0);
#define FI first
#define SE second
typedef long long ll;
typedef pair<int,int> P;
const int maxn = 2e5 + 7;
const int INF = 0x3f3f3f3f;
int n, x, y;
char s[maxn];
int x1[maxn], y1[maxn];
int x2[maxn], y2[maxn];
bool ok(int len) {
for(int i = 1; i <= n; ++i) {
int j = i + len - 1;
if(j > n) break;
int dx = x1[i-1] + x2[j + 1], dy = y1[i-1] + y2[j+1];
// cout << i << " : " << dx << " +++ " << dy << endl;
int cnt = abs(dx-x) + abs(dy-y);
if(cnt <= len && (len-cnt) % 2 == 0) return true;
}
return false;
}
void init() {
x1[0] = 0, y1[0] = 0;
for(int i = 1; i <= n; ++i) {
if(s[i] == 'U') {
x1[i] = x1[i-1];
y1[i] = y1[i-1] + 1;
}
if(s[i] == 'D') {
x1[i] = x1[i-1];
y1[i] = y1[i-1] - 1;
}
if(s[i] == 'L') {
x1[i] = x1[i-1] - 1;
y1[i] = y1[i-1];
}
if(s[i] == 'R') {
x1[i] = x1[i-1] + 1;
y1[i] = y1[i-1];
}
}
x2[n+1] = 0, y2[n+1] = 0;
for(int i = n; i >= 1;--i) {
if(s[i] == 'U') {
x2[i] = x2[i+1];
y2[i] = y2[i+1] + 1;
}
if(s[i] == 'D') {
x2[i] = x2[i+1];
y2[i] = y2[i+1] - 1;
}
if(s[i] == 'L') {
x2[i] = x2[i+1] - 1;
y2[i] = y2[i+1];
}
if(s[i] == 'R') {
x2[i] = x2[i+1] + 1;
y2[i] = y2[i+1];
}
}
}
int main() {
scanf("%d", &n);
scanf("%s", s+1);
scanf("%d%d", &x, &y);
if(abs(x) + abs(y) > n) {
return 0*puts("-1");
}
init();
int l = 0, r = n, ans = -1;
while(l <= r) {
int mid = (l + r) / 2;
// cout << mid << " : ";
if(ok(mid)) {
// cout << " YES " << endl;
ans = mid;
r = mid - 1;
}
else {
// cout << " NO " << endl;
l = mid + 1;
}
}
printf("%d\n", ans);
return 0;
}