2020ICPC·小米 网络选拔赛第二场 A-2020(二分答案)

2020ICPC·小米 网络选拔赛第二场 A-2020(二分答案)

题面:

题意:

给定一个只含有\(0,1,2\)的字符串,现在问你可以把字符串最多分成多少个互不相交的子序列,其中每一个子序列是\(2020\).

思路:

在区间\([0,\frac{n}{4}]\) 中二分答案,对于当前的需要check的答案\(mid\)

我们如下进行验证:

先找到\(mid\)个字符\(\text 2\),然后对于每一个\(\text 2\)找到其后方最近的\(\text 0\) 分给它作成\(20\)

然后对于每一个\(\text 20\)找到其后方最近的\(\text 2\) 分给它,作成\(202\)

,然后对于每一个\(\text 202\)找到其后方最近的\(\text 0\) 分给它作成\(2020\)

若能完成则返回true,否则为false。

代码:

#include<bits/stdc++.h>
using namespace std;
#define rep(i,a,n) for (int i=a;i<=n;++i)
#define per(i,n,a) for (int i=n;i>=a;--i)
#define sz(x) ((int)(x).size())
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define lson l,mid,p<<1
#define rson mid+1,r,p<<1|1
typedef pair<int, int> pii;
#define ll long long
const int inf = 1e9;
const int mod = 1e9 + 7;
const int N = 1e6 + 10;
int n;
char s[N];
int vis[N];
int vis1[N];
int vis2[N];
int used[N];
bool check(int mid)
{
    for (int i = 1; i <= n; ++i) {
        vis[i] = 0;
        vis1[i] = 0;
        vis2[i] = 0;
        used[i] = 0;
    }
    int num = 0;
    for (int i = 1; i <= n; ++i) {
        if (s[i] == '2') {
            if (num < mid) {
                num++;
                vis[i] = 1;
                used[i] = 1;
            }
        }
    }
    if (num < mid) {
        return 0;
    }
    num = 0;
    int cnt = 0;
    for (int i = 1; i <= n; ++i) {
        cnt += vis[i];
        if (s[i] == '0' && used[i] == 0) {
            if (cnt > 0 && num < mid) {
                cnt--;
                num++;
                vis1[i] = 1;
                used[i] = 1;
            }
        }
    }
    if (num < mid) {
        return 0;
    }
    num = 0;
    cnt = 0;
    for (int i = 1; i <= n; ++i) {
        cnt += vis1[i];
        if (s[i] == '2' && used[i] == 0) {
            if (cnt > 0 && num < mid) {
                cnt--;
                num++;
                used[i] = 1;
                vis2[i] = 1;
            }
        }
    }
    if (num < mid) {
        return 0;
    }
    num = 0;
    cnt = 0;
    for (int i = 1; i <= n; ++i) {
        cnt += vis2[i];
        if (s[i] == '0' && used[i] == 0) {
            if (cnt > 0 && num < mid) {
                cnt--;
                num++;
                used[i] = 1;
            }
        }
    }
    return num >= mid;
}
int main()
{
    //ios::sync_with_stdio(false);
    //freopen("in","r",stdin);
    while (~scanf("%d", &n)) {
        scanf("%s", s + 1);
        int l = 0;
        int r = n / 4;
        int mid;
        int ans = 0;
        while (l <= r) {
            mid = (l + r) >> 1;
            if (check(mid)) {
                ans = mid;
                l = mid + 1;
            } else {
                r = mid - 1;
            }
        }
        printf("%d\n", ans );
    }
    return 0;
}

posted @ 2020-10-31 21:35  茄子Min  阅读(232)  评论(0编辑  收藏  举报