【解题报告】Codeforces Round #402 (Div. 2)

来源:互联网 发布:win7 无法连接到网络 编辑:程序博客网 时间:2024/05/29 14:09

题目连接


A. Pupils Redistribution(Codeforces 779A)

思路

要让两个组得分数 i 的人数相等,那么两个组得分数i的人数和 sum[i] 要是偶数才行。那么通过 sum[i]2 次交换,就能使两组的分数i的人数相等。对所有的 i 同理可求交换次数。

代码

#include <bits/stdc++.h>using namespace std;const int maxn = 110;int n, foo, da, db, a[maxn], b[maxn], c[maxn];int main() {//  freopen("Input5.txt", "r", stdin);    ios::sync_with_stdio(false);    cin.tie(0);    cin >> n;    for(int i = 1; i <= n; i++) {        cin >> foo;        a[foo]++;        c[foo]++;    }    for(int i = 1; i <= n; i++) {        cin >> foo;        b[foo]++;        c[foo]++;    }    for(int i = 1; i <= 5; i++) {        if(c[i] % 2 == 1) {            puts("-1");            return 0;        }        c[i] /= 2;    }    for(int i = 1; i <= 5; i++) {        da += abs(a[i] - c[i]);        db += abs(b[i] - c[i]);    }    if(da != db || da % 2 == 1) {        puts("-1");        return 0;    }    cout << da / 2 << endl;    return 0;}

B. Weird Rounding(Codeforces 779B)

思路

从最低位向最高位遍历 n ,遇到 0 就统计当前出现的 0 的次数,遇到非 0 数就统计答案。当遇到 0 的次数等于 k 时遍历结束。统计到的答案就是最终答案。若遇到的 0 小于 k 次的话直接将所有数字删除就是结果。

代码

#include <bits/stdc++.h>using namespace std;string s;int k, a, b;int main() {//  freopen("Input3.txt", "r", stdin);    ios::sync_with_stdio(false);    cin.tie(0);    cin >> s >> k;    for(int i = s.size() - 1; i >= 0; i--) {        if(s[i] == '0') {            a++;        }        else {            b++;        }        if(a == k) {            cout << b << endl;            return 0;        }    }    cout << s.size() - 1 << endl;    return 0;}

C. Dishonest Sellers(Codeforces 779C)

思路

因为 n 件商品都要买,所以先买折扣大的。按照差价从大到小排序,第一天先买折扣最大的 k 件(哪怕有商品没有折扣也要买够 k 件)。然后第二天把剩下的买齐。

代码

#include <bits/stdc++.h>using namespace std;typedef long long ll;const int maxn = 2e5 + 10;int n, k, p, q, cnt, a[maxn], b[maxn];ll ans;struct item {    int a, b;    item() {}    item(int a, int b): a(a), b(b) {}    bool operator < (const item& o) const {        return (a - b) < (o.a - o.b);    }}items[maxn];int main() {//  freopen("Input2.txt", "r", stdin);    ios::sync_with_stdio(false);    cin.tie(0);    cin >> n >> k;    for(int i = 1; i <= n; i++) {        cin >> a[i];    }    for(int i = 1; i <= n; i++) {        cin >> b[i];    }    for(int i = 1; i <= n; i++) {        items[i] = item(a[i], b[i]);    }    sort(items + 1, items + n + 1);    for(int i = 1; i <= n; i++) {        p = items[i].a;        q = items[i].b;        if(p <= q) {            ans += p;            cnt++;        }        else if(cnt >= k) {            ans += q;        }        else {            ans += p;            cnt++;        }    }    cout << ans << endl;    return 0;}

D. String Game(Codeforces 779D)

思路

求最优解的问题。乍一看没什么贪心的思路。数据规模提示我们可能可以用二分法解决。于是二分最大的删除次数 x 。问题转化为判断在给定删除次数 x 内删除是否合法。显然我们可以在线性时间内将字符用“注释”的方式删除(不是真删除)。然后扫描“删除”后的字符串,看看要得到的字符串的每个字符是否按顺序在其中出现即可。

代码

#include <bits/stdc++.h>using namespace std;const int maxn = 2e5 + 5;string t, p;int l, r, mid, idx, deadLine[maxn];bool ok(int x) {    int j = 0;    for(int i = 0; i < t.size(); i++) {        if(deadLine[i] > x) {            if(t[i] == p[j] && ++j >= p.size()) {                return true;            }        }    }    return false;}int main() {//  freopen("Input2.txt", "r", stdin);    ios::sync_with_stdio(false);    cin.tie(0);    cin >> t >> p;    for(int i = 0; i < t.size(); i++) {        cin >> idx;        deadLine[idx - 1] = i + 1;    }    l = 0;    r = t.size();    while(r - l > 1) {        mid = (l + r) >> 1;        if(ok(mid)) {            l = mid;        }        else {            r = mid;        }    }    cout << l << endl;    return 0;}

(其它题目略)

0 0
原创粉丝点击