zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    110、抽象基类为什么不能创建对象?
    109、什么情况会自动生成默认构造函数?
    108、如果想将某个类用作基类,为什么该类必须定义而非声明?
    107、类如何实现只能静态分配和只能动态分配
    106、C++中的指针参数传递和引用参数传递有什么区别?底层原理你知道吗?
    hdoj--2036--改革春风吹满地(数学几何)
    nyoj--46--最少乘法次数(数学+技巧)
    vijos--P1211--生日日数(纯模拟)
    nyoj--42--一笔画问题(并查集)
    nyoj--49--开心的小明(背包)
  • 原文地址:https://www.cnblogs.com/lecoz/p/9919854.html
Copyright © 2011-2022 走看看