2025寒假专场12
增一减一
每次操作都会加一减一, 所有
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N = 2e5+10;
int n, m, idx;
int f[N];
signed main(){
cin >> n;
int sum = 0;
for(int i = 1; i <= n; i++) {
cin >> f[i];
sum += f[i];
}
sort(f + 1, f + 1 + n, greater<>());
int x = sum / n;
int y = sum % n;
for(int i = 1; i <= n; i++){
if(i <= y) idx += abs(f[i] - (x + 1));
else idx += abs(f[i] - x);
}
cout << idx / 2;
return 0;
}
绘制颜色
开一个数组
#include<bits/stdc++.h>
using namespace std;
const int N = 2e5 + 10;
int n, m;
int f[N], la[N];
char c[N];
int main(){
cin >> n >> m;
string s;
cin >> s;
for (int i = 0; i < n; i++) cin >> f[i];
for (int i = 0; i < n; i++) {
if (!c[f[i]]) { // 记录第一轮
c[f[i]] = s[i];
la[f[i]] = i;
}
else {
char x = c[f[i]];
c[f[i]] = s[i];
s[i] = x;
}
}
for (int i = 1; i <= m; i++) // 更新最前面的位置
s[la[i]] = c[i];
cout << s;
return 0;
}
字母操作
本题的处理难点在于由于数据范围较大, 我们不能每次输入都接着操作, 只能是读取所有操作之后最后进行处理; 因为每次更改大小写都是全部更改, 所以我们只看最后一个更改大小写的操作的位置last即可; 当t=1时, 我们可以记录这次操作是第几个操作, 当t=1的操作顺序在last之后就不需要改变大小写了;
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N = 5e5 + 10, mod = 998244353;
typedef pair<int, int> PII;
int n, m, idx;
int sp;
int nu[N];
signed main(){
string s;
cin >> n >> s;
s = ' ' + s;
cin >> m;
for(int i = 1; i <= m; i++) {
int a, b;
char c;
cin >> a >> b >> c;
if (a == 1) {
s[b] = c;
nu[b] = i;
}
else if (a == 2) {
sp = 1;
idx = i;
}
else {
sp = 2;
idx = i;
}
}
for (int i = 1; i <= n; i++) {
if (nu[i] > idx) continue;
else {
if (sp == 1 && isupper(s[i])) s[i] += 32;
if (sp == 2 && islower(s[i])) s[i] -= 32;
}
}
for (int i = 1; i <= n; i++) cout << s[i];
return 0;
}
魔幻的饼干
考虑模拟; 那么我们要遍历所有字母, 并且操作完之后还要重复上述过程, 大致相当于
当我们删除一行时, 可能会由此出现新的满足条件的列, 所以最外层的
和
首先我们先遍历行
#include<bits/stdc++.h>
using namespace std;
const int N = 2e3 + 10, mod = 998244353;
typedef pair<int, int> PII;
int n, m, res;
char g[N][N];
int st[N][N], fst[N][N];
int rs[N], cs[N];
bool ro[N], co[N];
int main(){
cin >> n >> m;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
cin >> g[i][j];
st[i][g[i][j] - 'a']++; // 统计行的字母
fst[j][g[i][j] - 'a']++;// 统计列的字母
}
}
for (int i = 1; i <= n; i++) rs[i] = m;//第i行长度
for (int j = 1; j <= m; j++) cs[j] = n;//第j列长度
while (1) {
vector<int> rv, cv;
bool qu = false;
for (int i = 1; i <= n; i++) {
if (ro[i]) continue;
for (int j = 0; j < 26; j++) {
if (st[i][j] == rs[i] && st[i][j] >= 2) {
qu = true;
ro[i] = true;
st[i][j] = 0;
rv.push_back(j);
}
}
}
for (int i = 1; i <= m; i++) {
if (co[i]) continue;
for (int j = 0; j < 26; j++) {
if (fst[i][j] == cs[i] && fst[i][j] >= 2) {
qu = true;
co[i] = true;
fst[i][j] = 0;
cv.push_back(j);
}
}
}
for (int x : rv) {
for (int i = 1; i <= m; i++) {
fst[i][x]--;
cs[i]--;
}
}
for (int x : cv) {
for (int i = 1; i <= n; i++) {
st[i][x]--;
rs[i]--;
}
}
if (!qu) {
break;
}
}
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
if (!ro[i] && !co[j]) {
res++;
}
}
}
cout << res;
return 0;
}
/*
4 3
aab
aaa
abc
cbd
*/
竞选
01背包:
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int INF=0x3f3f3f3f3f3f3f3f;
const int N = 110, M = 1e5 + 10;
int A[N], B[N], C[N];
int dp[M];
signed main(){
int n;
cin>>n;
int sum = 0;
for(int i = 1; i <= n; i++)
cin >> A[i] >> B[i] >> C[i], sum += C[i];
//01背包-->dp[i]表示赢得i个席位需要转移的最少人数
memset(dp,127,sizeof(dp));
dp[0] = 0;
for(int i = 1; i <= n; i++){
for(int j = sum; j >= C[i]; j--){
if(A[i] > B[i]) dp[j] = min(dp[j - C[i]], dp[j]);
else dp[j] = min(dp[j - C[i]] + (A[i] + B[i] + 1) / 2 - A[i], dp[j]);
}
}
int ans = INF;
for(int i = (sum + 1) / 2; i <= sum; i++)
ans = min(ans, dp[i]);
cout << ans;
return 0;
}