CodeForces - 1465D.Grime Zoo (贪心+思维)
题意
给出一个包含 0 1 ? 0 1 ? 0 1 ? 的序列 每个子序列 01 01 01会增加 x x x点愤怒值,每个子序列 10 10 10会增加 y y y点愤怒值
用 0 1 0 1 0 1代替所有的 ? ? ? 使得最终的愤怒值最小
思路
先用 1 1 1 代替所有的 ? ? ? 求出每个位置前缀和后缀中 1 0 ? 1 0 ? 1 0 ? 的数量 计算得到当前愤怒值 $re
如果 x < y x < y x<y 贪心地使得 01 01 01 多 10 10 10 少 即从前往后地将 ? ? ? 用 0 0 0 替换 遍历每种情况 求最小值
如果 x > y x > y x>y 贪心地使得 10 10 10 多 01 01 01 少 即从后往前地将 ? ? ? 用 1 1 1 替换 遍历每种情况 求最小值
p s : ps: ps: 在求最小值的过程中 刚开始我用
int x = vec[i];
导致变量名重复 de了半天bug愣是没找到错在哪 😅
代码
#include<bits/stdc++.h> #define INF 0x3f3f3f3f #define mod 1000000007 using namespace std; typedef long long LL; typedef pair<int, int>PII; inline LL gcd(LL a, LL b) { return b ? gcd(b, a % b) : a; } const int N = 100010; LL x, y; char s[N]; int st[N][3], ed[N][3]; //记录前缀、后缀中 0、1、?的个数 vector<int>vec; void solve() { scanf("%s", s + 1); cin >> x >> y; int len = strlen(s + 1); for (int i = 1; i <= len; ++i) { //前缀 st[i][0] = st[i - 1][0]; st[i][1] = st[i - 1][1]; st[i][2] = st[i - 1][2]; if (s[i] == 0)st[i][0]++; else if (s[i] == 1)st[i][1]++; else { vec.push_back(i); st[i][2]++; } } for (int i = len; i >= 1; --i) { //后缀 ed[i][0] = ed[i + 1][0]; ed[i][1] = ed[i + 1][1]; ed[i][2] = ed[i + 1][2]; if (s[i] == 0)ed[i][0]++; else if (s[i] == 1)ed[i][1]++; else ed[i][2]++; } LL sum0 = 0, sum1 = 0; LL ans = 0; for (int i = 1; i <= len; ++i) { //先求出把 ? 当作 1 时的的“愤怒值” if (s[i] == 0) { ans += sum1 * y; sum0++; } else { ans += sum0 * x; //把 ? 先看做是 1 sum1++; } } LL res = ans; if (x < y) { //把 ? 当作 1 尽量放在前面 从后往前 将 ? 用 0 替换 遍历每种情况求最小值 for (int i = 0; i < vec.size(); ++i) { int idx = vec[i]; res = res - (st[idx - 1][0] + st[idx - 1][2]) * x - ed[idx + 1][0] * y; res = res + st[idx - 1][1] * y + (ed[idx + 1][1] + ed[idx + 1][2]) * x; ans = min(res, ans); } } else { //把 ? 当作 1 尽量放在后面 从前往后 将 ? 用 0 替换 遍历每种情况求最小值 for (int i = vec.size() - 1; i >= 0; --i) { int idx = vec[i]; res = res - st[idx - 1][0] * x - (ed[idx + 1][0] + ed[idx + 1][2]) * y; res = res + (st[idx - 1][1] + st[idx - 1][2]) * y + ed[idx + 1][1] * x; ans = min(res, ans); } } cout << ans << endl; } int main() { //int t; cin >> t; //while (t--) solve(); return 0; }