CF-552E-Two Teams

pro:给出n, k和长度为n的数组a, 两个人轮流取数1先取,设a[i]是当前数组中最大值,则取走a[i - k]到a[i + k]这段数,然后把a[i + k + 1]和后面的补到 a[i - k]的位置。(当然要考虑前后边界,i - k不能小于1,i + k不能大于n)输出一个字符串s[i]表示a[i]属于1或2;

sol:要解决的就是把a[i + k + 1]后面的往前移的操作,可以不用移,建两个数组,lft[i]表示i的上一个数下标,rgt[i]表示i下一个数的下标。

  • 有点像HDU1698用并查集解决的骚操作,都是标记上一个数或下一个数
    E - Two Teams GNU C++11 Accepted 46 ms 3300 KB
    #include "bits/stdc++.h"
    using namespace std;
    const int MAXN = 2e5 + 5;
    int a[MAXN], b[MAXN], lft[MAXN], rgt[MAXN];
    char ans[MAXN];
    int n, k, d = 1;
    void del(int t) {
        ans[t] = d ^ '0';
        lft[rgt[t]] = lft[t];
        rgt[lft[t]] = rgt[t];
    }
    int main() {
        scanf("%d%d", &n, &k);
        for (int i = 1; i <= n; i++) {
            scanf("%d", &a[i]);
            b[a[i]] = i;
            lft[i] = i - 1;
            rgt[i] = i + 1;
        }
        for (int i = n; i >= 1; i--) {
            int m = b[i];
            if (ans[m]) continue;
            del(m); 
            m = lft[m];
            for (int j = 0; j < k && m >= 1; j++) del(m), m = lft[m];
            m = rgt[m];
            for (int j = 0; j < k && m <= n; j++) del(m), m = rgt[m];
            d = 3 - d;
        }
        puts(ans + 1);
        return 0;
    }

    C++真好用,看到有人用STL里的东西来暴力,1900+ms卡过去了。本来想尝试hack一下的,数据太大无法提交。

猜你喜欢

转载自www.cnblogs.com/Angel-Demon/p/10726358.html