CodeForces Global Round 11 B. Chess Cheater 贪心,处理技巧

CodeForces Global Round 11 B. Chess Cheater 贪心,处理技巧

题意

有一段(WL)序列表示输赢,若是(W)则加一分,若前一个是(W)则额外加一分

现有(K)次操作可以把(L)变成(W),问最大的分数是多少

[1leq nleq 10^5\ 0leq k leq n ]

分析

显然我们需要修改(L)来加分,如果没有“额外”的规则,那么加在哪里都一样,有了规则后,加入一段(W)后就有了三种可能:

[2 imes k - 1\ 2 imes k\ 2 imes k + 1 ]

我们自然会贪心的选择最好的策略。

发现如果是第三种可能,每加入一段后就会额外多1分,那么我们当然希望第三种越多越好

于是可以对每个(L)区间按长度排序,贪心选择长度短的区间。

其他可能就是前面或者最后连续的一段(L),处理方法就是初始化为(cnt)一个大于(k)的数。这样就一定会被排序到最后面。、

最后连续的(L)只需要把剩下的(2 imes k)加入答案即可(具体见代码),因为最后总可以对答案取一个(max)

代码

char s[100005];

void solve() {
    int n = readint();
    int k = readint();
    scanf("%s", s);
    vector<int> v;
    int cnt = k + 5;
    int res = 0;
    for (int i = 0; i < n; i++) {
        if (s[i] == 'W') {
            if (i && s[i - 1] == 'W') res += 2;
            else res++;
        }
        else cnt++;
    }
    cnt = k + 5;
    for (int i = 0; i < n; i++) {
        if (s[i] != 'L') v.push_back(cnt), cnt = 0;
        //else if (i == n - 1) {
        //    if (s[i] == 'L') cnt++;
        //    v.push_back(cnt);
        //}
        else cnt++;
    }
    if (cnt == 5 + k + n) {
        printf("%d
", max(0, 2 * k - 1));
        return;
    }
    sort(v.begin(), v.end(), greater<int>{});
    while (!v.empty() && v.back() == 0) v.pop_back();
    reverse(v.begin(), v.end());
    for (int i = 0; i < v.size() && k > 0   ; i++) {
        if (k >= v[i]) k -= v[i], res += 2 * v[i] + 1;
    }
    res += 2 * k;
    res = min(res, 2 * n - 1);
    Put(res);
    puts("");
}


int main() {
    int T = readint();
    while (T--)
        solve();
}
原文地址:https://www.cnblogs.com/hznumqf/p/13817715.html