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();
}