Educational Codeforces Round 53 (Rated for Div. 2) C. Vasya and Robot 二分+前字尾預處理

ACVoyager發表於2018-11-03

題意:

給定長度為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;
}

 

相關文章