B. Chess Cheater (sort + greedy) Codeforces Global Round 11

Link to the original question: https://codeforces.com/contest/1427/problem/B

Insert picture description here
Test sample

input
8
5 2
WLWLL
6 5
LLLWWL
7 1
LWLWLWL
15 5
WWWLLLWWWLLLWWW
40 7
LLWLWLWWWLWLLWLWWWLWLLWLLWLLLLWLLWWWLWWL
1 0
L
1 1
L
6 1
WLLWLW
output
7
11
6
26
46
0
1
6

Note

Explanation of the first testcase. Before changing any outcome, the score is 2. Indeed, you won the first game, so you got 1 point, and you won also the third, so you got another 1 point (and not 2 because you lost the second game).
An optimal way to cheat is to change the outcomes of the second and fourth game. Doing so, you end up winning the first four games (the string of the outcomes becomes WWWWL). Hence, the new score is 7=1+2+2+2: 1 point for the first game and 2 points for the second, third and fourth game.

Explanation of the second testcase. Before changing any outcome, the score is 3. Indeed, you won the fourth game, so you got 1 point, and you won also the fifth game, so you got 2 more points (since you won also the previous game).
An optimal way to cheat is to change the outcomes of the first, second, third and sixth game. Doing so, you end up winning all games (the string of the outcomes becomes WWWWWW). Hence, the new score is 11=1+2+2+2+2+2: 1 point for the first game and 2 points for all the other games.

Meaning: you have nnThe wins and losses of n consecutive matches. The current scoring rules are as follows: if you win a game, then the score is 1, if you belong to a winning streak, then the score is 2. In other words, if you win the current game and the previous game also wins, then the current game score is 2. Now you can performkkK modification operations, ask the maximum score that can be obtained after modification.

Problem-solving ideas: a very good question. The first thing we need to know is how do we calculate the score?Suppose the number of games won is wins winsw i n s , the number ofwins thatdid not win the last hand iswins _ streaks; wins\_streaks;w i n s _ s t r e a k s ;, then the score situation isscore = wins ∗ 2 − ​​wins _ streaks score=wins*2-wins\_streaksscore=wins2wins_streaksThe calculation principle is to assume that the score is 2 22,而 w i n s _ s t r e a k s wins\_streaks w i n s _ s t r e a k s is a score of1 11 , so subtract the excess. This is the score for which we did nothing. Now you can modify the operation, then we will definitely change what we lose and where we will change. This is the problem we want to solve.According to the principle of greed, if we can dd the gap between two winsd (that is, the number of games lost) becomes a win, so this time we get the most points.Because we not only obtained 2 × d 2\times d2×The score of d still needs to be turned into a winning streak on the right, which is one more point. So our task is equivalent to filling the gap. If there is no gap to fill, then we can still get2 × k 2\times k at most.2×The score of k , that is to say, every time we fill a gap, we add one more point, which is equivalent to onewins _ streaks − − wins\_streaks--wins_streaks Operation. According to this, we only need to accumulate the length of the gap, and then fill in the gap that we can make up. The final score calculation formula is stillwins × 2 − wins _ streaks wins\times 2-wins\_streakswins×2w i n s _ s t r e a k s . Therefore, this question is easy to solve and some details should be paid attention to, which have been explained in the code.

AC code

/*
*邮箱:[email protected]
*blog:https://me.csdn.net/hzf0701
*注:文章若有任何问题请私信我或评论区留言,谢谢支持。
*
*/
#include<bits/stdc++.h>	//POJ不支持

#define rep(i,a,n) for (int i=a;i<=n;i++)//i为循环变量,a为初始值,n为界限值,递增
#define per(i,a,n) for (int i=a;i>=n;i--)//i为循环变量, a为初始值,n为界限值,递减。
#define pb push_back
#define IOS ios::sync_with_stdio(false);cin.tie(0); cout.tie(0)
#define fi first
#define se second
#define mp make_pair

using namespace std;

const int inf = 0x3f3f3f3f;//无穷大
const int maxn = 1e5;//最大值。
typedef long long ll;
typedef long double ld;
typedef pair<ll, ll>  pll;
typedef pair<int, int> pii;
//*******************************分割线,以上为自定义代码模板***************************************//

int t,n,k;
string s;
int main(){
    
    
	//freopen("in.txt", "r", stdin);//提交的时候要注释掉
	IOS;
	while(cin>>t){
    
    
		while(t--){
    
    
			cin>>n>>k;
			cin>>s;
			int wins=0,losses=0,wins_streaks=0;
			vector<int> losing_streaks;//这个用于统计间隙。
			rep(i,0,n-1){
    
    
				if(s[i]=='W'){
    
    
					if(i==0||s[i-1]=='L'){
    
    
						//说明是一个赢单数。
						wins_streaks++;
					}
					wins++;//统计原本赢得场数。
				}
				else{
    
    
					losses++;//统计原本数的场数。
					if(i==0||s[i-1]=='W'){
    
        
						//说明一个新的输的间隙开始了。
						losing_streaks.push_back(0);
					}
					losing_streaks.back()++;//尾部输的间隙+1,。
				}
			}
			//知道了这样的操作,接下来进行特判。
			if(k>=losses){
    
    
				//说明我们可以直接补完所有输的场数。
				cout<<2*n-1<<endl;
				continue;
			}
			if(wins==0){
    
    
				//说明我们没有一场赢,那么我们补的话一定是补连续的。
				if(k==0){
    
    
					cout<<0<<endl;
				}
				else{
    
    
					cout<<2*k-1<<endl;
				}
				continue;
			}
			//我们知道我们统计的第一个间隙和最后一个间隙可能没有被w包围。
			if(s[0]=='L'){
    
    
				losing_streaks[0]=inf;
			}
			if(s[n-1]=='L'){
    
    
				losing_streaks.back()=inf;
			}
			sort(losing_streaks.begin(),losing_streaks.end());
			int len=losing_streaks.size();
			wins+=k;
			rep(i,0,len-1){
    
    
				if(losing_streaks[i]>k){
    
    
					break;
				}
				else{
    
    
					wins_streaks--;
					k-=losing_streaks[i];
				}
			}
			cout<<2*wins-wins_streaks<<endl;
		}
	}
	return 0;
}

Guess you like

Origin blog.csdn.net/hzf0701/article/details/109007454