Loading

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

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

题意

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

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

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

分析

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

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

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

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

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

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

最后连续的\(L\)只需要把剩下的\(2\times 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\n", 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();
}
posted @ 2020-10-14 22:05  MQFLLY  阅读(130)  评论(0编辑  收藏  举报