CodeForce Educational round Div2 C

 
题意:给你长度为n的字符串,每个字符为L, R, U, D。给你终点位置(x, y)。你每次出发的起点为(0, 0)。你可以改动每次的移动方向到达(x,y)点。求改动的MaxID-MinID+1是多少。

思路:

先分别求x轴,y轴上的前缀和,偏于之后判断区间是否满足条件。详细见代码。

固定左端点,二分枚举右端点。判断左右端点的区间是否能够达成目标(区间长度是否大于未完成量,奇偶性是否相同)

注意点:

strlen是O(n)的复杂度,超时了。

之前没遇到过固定一个点,然后另一个点二分逼近值的。

#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <stack>
#define ll long long
#define local

using namespace std;

const int MOD = 1e9+7;
const int inf = 0x3f3f3f3f;
const double PI = acos(-1.0);
const int maxn = 2e5+10;

int n;
ll endx, endy;
ll total;
char str[maxn];
int sumx[maxn];
int sumy[maxn];

bool ok(int l, int r) {
    int nowx = sumx[n-1]-sumx[r];
    int nowy = sumy[n-1]-sumy[r];
    if (l > 0) {
        nowx += sumx[l-1];
        nowy += sumy[l-1];
    }
    ll diff = abs(endx-nowx)+abs(endy-nowy);
    if (diff <= r-l+1 && ((diff&1))==((r-l+1)&1)) return 1;
    else return 0;
}

int main() {
#ifdef local
    if(freopen("/Users/Andrew/Desktop/data.txt", "r", stdin) == NULL) printf("can't open this file!
");
#endif
    scanf("%d", &n);
    scanf("%s", str);
    scanf("%lld%lld", &endx, &endy);
    total = abs(endx)+abs(endy);//总的步数
    //如果两者奇偶性不同也不行
    if (total>n || ((total&1) != (n&1))) {
        printf("-1
");
        return 0;
    }
    sumx[0] = 0;
    sumy[0] = 0;
    int len = int(strlen(str));//strlen(str)是O(n)的复杂度 orz...
    for (int i = 0; i < len; ++i) {
        int incx  = 0; int incy = 0;
        if (str[i] == 'U') {
            incy = 1;
        } else if (str[i] == 'R') {
            incx = 1;
        } else if (str[i] == 'D') {
            incy = -1;
        } else {
            incx = -1;
        }
        if (i) {
            sumx[i] += sumx[i-1]+incx;
            sumy[i] += sumy[i-1]+incy;
        }
        else {
            sumx[i] = incx;
            sumy[i] = incy;
        }
    }
    if (sumx[n-1]==endx && sumy[n-1]==endy) {
        printf("0
");
        return 0;
    }
    int mn = inf;
    //枚举点
    for (int i = 0; i < n; ++i) {
        int l = i-1; int r = n-1;
        while (r-l > 1) {
            int m = (l+r)>>1;
            if (ok(i, m)) {
                r = m;
            } else {
                l = m;
            }
        }
        //判断一下r是否可行
        if (ok(i, r)) mn = min(mn, r-i+1);
    }
    printf("%d
", mn);
#ifdef local
    fclose(stdin);
#endif
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/lecoz/p/9919854.html