Codeforces Round #692

CF 1463 D. Grime Zoo

题意

给一个包含 '?' 的 01 串, 你可以在 '?' 中填入 0 或 1

每一个 '01' 子串会贡献 (x) 的恶评, '10' 子串会贡献 (y) 的恶评

求最小恶评值

当时思考情况:

想到了当 0 的个数和 1 的个数确定的时候一定是把 0 放一边,把 1 放在另一边。

但是我不知道在问号其他位置有 0,1 的时候是不是也是分两边放。

当时我算了每个问号取 0 时候的贡献和取 1 的贡献,然后我把问题转换为了 选的贡献加上问号之间的贡献

问号之间的贡献最小肯定是选一边的 0 和一边的 1, 但是还要考虑对本有数字的贡献。我当时的思考就在这里停下了。

其实就算有数字这个结论也是成立的,因为:

假设 0 和 1 的个数已经确定了, 在问号处先随机填入 0 和 1

当我们交换问号处的 0 和 1 的时候(0 在前面), 其实就是把若干个 '01' 变成了 '10'

交换 1 和 0 的时候(1 在前面), 就是把 '10' 变成了 '01' ,很显然我们需要一直往一个方向去靠,最后就会变成一堆 0 和一堆 1.

/*
 * @Author: zhl
 * @LastEditTime: 2020-12-23 14:29:24
 */
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N = 1e5 + 10;
typedef long long ll;

char s[N];
int x, y, s0[N], s1[N], pos[N], tot;
ll sw0[N], sw1[N];
signed main() {
	scanf("%s", s + 1); int n = strlen(s + 1);
	scanf("%lld%lld", &x, &y); ll res = 0;
	for (int i = 1; i <= n; i++) {
		s0[i] = s0[i - 1] + (s[i] == '0');
		s1[i] = s1[i - 1] + (s[i] == '1');
		res += (s[i] == '0') * s1[i] * y;
		res += (s[i] == '1') * s0[i] * x;
	}
	for (int i = 1; i <= n; i++) {
		if (s[i] == '?') {
			pos[++tot] = i;
			sw0[tot] = sw0[tot - 1] + s1[i] * y + (s1[n] - s1[i]) * x;
			sw1[tot] = sw1[tot - 1] + s0[i] * x + (s0[n] - s0[i]) * y;
		}
	}
	ll ans = 1e18;
	for (int i = 1; i <= tot; i++) {
		ans = min(ans, i * (tot - i) * x + sw0[i] + sw1[tot] - sw1[i]);
		ans = min(ans, i * (tot - i) * y + sw1[i] + sw0[tot] - sw0[i]);
	}
	if (ans == 1e18)ans = 0;
	cout << res + ans << endl;
}

CF 1463 E. Poman Numbers

给一个字符串和一个函数

[f(S) = egin {cases}2^{pos(S[1])} &&|S|=1\\-f(S(1,m)) + f(S(m+1,|S|)),&&|S| > 1end{cases} ]

问能不能凑出一个数 (K) ,通过有目的的选取每次的 (m)

有个结论,f[n] 的系数是 + ,f[n-1] 是 -,其他的任意

于是可以贪心做,贪心向绝对值最小的方向去搞,暂时不懂这个贪心为啥是对的。

/*
 * @Author: zhl
 * @LastEditTime: 2020-12-23 15:21:41
 */
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;

typedef long long ll;
ll n, k;
string s;
int main() {
	cin >> n >> k;
	cin >> s;
	ll m = k - (1ll << (s[n - 1] - 'a')) + (1ll << (s[n - 2] - 'a'));
	vector<int>cnt(26, 0);
	for (int i = 0; i < n - 2; i++)cnt[s[i] - 'a']++;
	for (int i = 25; i >= 0; i--) {
		while (cnt[i]--) {
			ll x = m - (1ll << i), y = m + (1ll << i);
			m = abs(x) < abs(y) ? x : y;
		}
	}
	cout << ((m == 0) ? "Yes" : "No") << endl;
}
原文地址:https://www.cnblogs.com/sduwh/p/14178940.html