不可能都讲,都挺水的,讲几道我觉得有意思的

E 距离

题意

每次操作修改一对关系,问所有关系的最值

大概思路

有点像莫队的思想,用一个神奇的map迭代器就能过。

代码

void solve(){
    int n, m;
    std::cin >> n >> m;
    std::map<std::pair<int, int>, int> f;
    std::map<int, int> cnt;

    while (m--) {
        int op, a, b, c;
        std::cin >> op >> a >> b >> c;

        if (op == 1) {
            cnt[f[{a, b}]]--;
            if (cnt[f[{a, b}]] == 0) cnt.erase(f[{a, b}]);
            f[{a, b}] += c;
            cnt[f[{a, b}]]++;
        } else {
            cnt[f[{a, b}]]--;
            if (cnt[f[{a, b}]] == 0) cnt.erase(f[{a, b}]);
            f[{a, b}] -= c;
            cnt[f[{a, b}]]++;
        }
        std::cout << cnt.rbegin()->first << "\n";//rbegin()取最大值,begin()取最小值
    }
}

H 考试

题意

给定等长度数组a,b,可以做任意次操作,将数组a的某个元素值增加,求最小的增加量总和,使得满足 $a[i] > b[i]$ 的i个数严格大于满足 $a[i] < b[i]$ 的i个数。

大概思路

一个有趣的贪心,模拟一下就过了

代码

void solve(){
    int n;
    std::cin >> n;

    std::vector<int> a(n), b = a;
    for (auto &i : a) std::cin >> i;
    for (auto &i : b) std::cin >> i;

    std::vector<int> c;
    int win = 0;//胜
    int fail = 0;//负
    int ping = 0;//平
    for (int i = 0; i <n; i++) {
        if (a[i] > b[i]) win++;
        else if (a[i] == b[i]) ping++;
        else {
            c.push_back(b[i] - a[i]);
            fail++;
        }
    }

    std::sort(c.begin(), c.end());
    i64 sum = 0;
    int i = 0;
    while (win <= fail) {
        if (ping) {//贪心选择平局,因为平局只要花费1的代价就能让fail-win的值减1
            ping--;
            win++;
            sum++;
        } else {//贪心地指增到刚好能让fail减少1的程度,构造一个平局,留给上面进行下一轮贪心
            //(为什么不干脆顺便加1?因为有可能这里fail--后就可以退出while循环了,没必要再加1使win++)
            fail--;
            ping++;
            sum += c[i++];
        }
    }
    std::cout << sum; 
}