[题解]CF1800B Count the Number of Pairs

题意

给定一个字符串 \(S\),你可以进行 \(k\) 次操作,每次操作你可以选定一个 \(i\),并将 \(S_i\) 的大小写转换。

求:操作后,最多有几组配对的字符。(配对的定义是:对于一个字符,如果有大写,有小写被称之为一组。例如:Aa 为一组。)

思路

你在读入的时候,你预处理一个数组 \(vis_{c,0/1}\) 表示,\(c\) 这个字符的大写/小写出现的次数。

然后,你就暴力判断 \(|vis_{s_i,0} - vis_{s_i,1}|\) 是否大于 \(1\),如果大于 \(1\) 才有变换的意义;否则直接将答案加上它。

对于每一次变换,你判断一下 \(\lfloor \frac{|vis_{s_i,0} - vis_{s_i,1}|}{2} \rfloor\) 和当前 \(k\) 的关系,然后加答案即可。

Code

#include <bits/stdc++.h>  
#define re register  
  
using namespace std;  
  
const int N = 27;  
int T,n,k,ans;  
int vis[N][2];  
string s;  
  
inline int get(char c){  
    if (c >= 'A' && c <= 'Z') return c - 'A' + 1;  
    return c - 'a' + 1;  
}  
  
int main(){  
    ios::sync_with_stdio(0);  
    cin.tie(0);  
    cout.tie(0);  
    cin >> T;  
    while (T--){  
        memset(vis,0,sizeof(vis));  
        cin >> n >> k >> s;  
        ans = 0;  
        s = ' ' + s;  
        for (re int i = 1;i <= n;i++){  
            if (s[i] >= 'A' && s[i] <= 'Z') vis[get(s[i])][0]++;//统计   
            else vis[get(s[i])][1]++;  
        }  
        for (re int i = 1;i <= 26;i++){  
            int t = abs(vis[i][0] - vis[i][1]);  
            if (t <= 1) ans += min(vis[i][0],vis[i][1]);//判断是否要进行变换   
            else{  
                int cnt = t >> 1;  
                if (cnt <= k){//如果要变换的次数小于等于 k 就可以全部变换   
                    ans += min(vis[i][0],vis[i][1]) + cnt;  
                    k -= cnt;  
                }  
                else{//否则,只能变换 k 次   
                    ans += min(vis[i][0],vis[i][1]) + k;  
                    k = 0;  
                }  
            }  
        }  
        printf("%d\n",ans);  
    }  
    return 0;  
}  
posted @ 2024-06-25 12:27  WBIKPS  阅读(27)  评论(0)    收藏  举报