zoukankan      html  css  js  c++  java
  • 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;
    }
    
  • 相关阅读:
    Vim配置IDE开发环境
    Win7任务计划自由预设系统定时自动关机
    awk中文手册
    awk简明教程
    Linux之mount命令详解
    VirtualBox内Linux系统与Windows共享文件夹
    堆排序详解
    int main(int argc,char* argv[])参数详解
    GDB调试详解
    VirtualBox中虚拟Ubuntu添加新的虚拟硬盘
  • 原文地址:https://www.cnblogs.com/sduwh/p/14178940.html
Copyright © 2011-2022 走看看