Face Produces Unhappiness(贪心)
题意
给定长度为\(N\)的串\(S\),如果\(S_i\)等于L
,说明第\(i\)个人面朝左边,反之则朝向右边。
若\(S_i\)和\(S_{i+1}\)方向相同,则高兴值加\(1\)。
现在有一种操作操作:选择一个\(L\)和\(R\),将\([L, R]\)序列逆序,并且将L
变成R
,R
变成L
。如:对LLLRLL
操作,得到RRLRRR
。
最多可以进行\(K\)次操作。问操作结束之后的最大高兴值是多少。
题目链接:https://atcoder.jp/contests/abc140/tasks/abc140_d
数据范围
\(1 \leq N, K \leq 10^5\)
思路
训练时猜了一个贪心思路:不妨设第一个字符为L
,将\(K\)段(如果不满\(K\)段,则为全部)连续的R
进行操作,操作后的序列高兴值即为答案。
这个贪心思路是正确的,下面对其进行简单解释。每次操作可以增加高兴值\(2\)或者\(1\)。当形如LRRRL
时,对中间的RRR
进行操作,可以增加高兴值\(2\);当LRRR
时,对RRR
操作可以增加高兴值\(1\)。我们优先选取第一种情况,因此顺着序列对连续的R
进行操作即可。
代码
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 100010;
int n, k;
char s[N];
int main()
{
scanf("%d%d%s", &n, &k, s + 1);
int ans = 0;
char st = s[1];
for(int i = 2; i <= n; i ++) {
if(s[i] != st && k) {
int j = i;
while(j <= n && s[j] != st) s[j] = st, j ++;
k --;
i = j - 1;
}
}
for(int i = 2; i <= n; i ++) {
if(s[i] == s[i - 1]) ans ++;
}
printf("%d\n", ans);
return 0;
}