Codeforces Round #611 (Div. 3)

比赛链接:https://codeforces.com/contest/1283

A - Minutes Before the New Year

题意

计算当前时间距离 $24:00$ 还有多少分钟。

Tips

小时要从 $23$ 减起。

代码

#include <bits/stdc++.h>
using namespace std;

void solve() {
    int h, m; cin >> h >> m;
    cout << 60 * (23 - h) + (60 - m) << "\n";
}

int main() {
    int t; cin >> t;
    while (t--) solve();
}

B - Candies Division

题意

将 $n$ 个糖果分给 $k$ 个小朋友,要求所有小朋友分得的糖果数两两之差不多于 $1$,且分得最多糖果个数的小朋友不超过 $\lfloor \frac{k}{2} \rfloor$,可以保留一些糖果,问最多能分出多少糖果。

思路

先尽可能地平分糖果,然后加上 $\lfloor \frac{k}{2} \rfloor$ 和余下糖果中较小的值。

代码

#include <bits/stdc++.h>
using namespace std;

void solve() {
    int n, k; cin >> n >> k;
    int mi = n / k;
    cout << mi * k + min(k / 2, n - mi * k) << "\n";
}

int main() {
    int t; cin >> t;
    while (t--) solve();
}

C - Friends and Gifts

题意

有 $n$ 个小朋友互赠礼物,但有的小朋友不知道该送给谁,试补全方案使得每个小朋友都能给出和得到一个礼物(不能自己送给自己)。

思路一

分别记录没有给出和得到礼物的小朋友,让既没有给出也没有得到礼物的小朋友们错位相赠,其余小朋友们互赠就可以了。

代码一

#include <bits/stdc++.h>
using namespace std;
int main() {
    int n; cin >> n;
    int f[n + 1] = {};
    bool get[n + 1] = {}, give[n + 1] = {}; 
    for (int i = 1; i <= n; i++) {
        cin >> f[i];
        if (f[i] != 0) {
            give[i] = true;
            get[f[i]] = true;
        }
    }
    set<int> a, b;
    for (int i = 1; i <= n; i++) {
        if (!give[i]) a.insert(i);
        if (!get[i]) b.insert(i); 
    }
    vector<int> v;
    for (int i = 1; i <= n; i++) {
        if (a.count(i) and b.count(i)) {
            a.erase(i);
            b.erase(i);
            v.push_back(i);
        }
    }
    if (v.size() == 1) {
        f[v[0]] = *b.begin();
        b.erase(b.begin());
        b.insert(v[0]);
    } else {
        for (int i = 0; i < v.size(); i++)
            f[v[i]] = v[(i + 1) % v.size()];
    }
    for (int give : a) {
        auto it = b.begin();
        f[give] = *it++;
    }
    for (int i = 1; i <= n; i++) cout << f[i] << ' ';
}

思路二

分别记录没有给出和得到礼物的小朋友,如果存在自己送给自己的小朋友让前一个给出礼物的小朋友送给他,他送给前一个得到礼物的小朋友,因为前一对是两个不同的小朋友相赠的。

代码二

#include <bits/stdc++.h>
using namespace std;
int main() {
    int n; cin >> n;
    bool get[n + 1] = {}, give[n + 1] = {};
    int f[n + 1] = {}; 
    for (int i = 1; i <= n; i++) {
        cin >> f[i];
        if (f[i] != 0) {
            give[i] = true;
            get[f[i]] = true;
        }
    }
    vector<int> a, b;
    for (int i = 1; i <= n; i++) {
        if (!give[i]) a.push_back(i);
        if (!get[i]) b.push_back(i);
    }
    for (int i = 0; i < a.size(); i++) {
        if (a[i] == b[i]) {
            if (i == 0) swap(a[i], a[i + 1]);
            else swap(a[i], a[i - 1]);
        }
    }
    for (int i = 0; i < a.size(); i++) {
        f[a[i]] = b[i];
    }
    for (int i = 1; i <= n; i++) cout << f[i] << ' ';
}

D - Christmas Trees

题意

有 $n$ 棵圣诞树和 $m$ 个人,已知数轴上 $n$ 棵圣诞树的位置,找出 $m$ 个位置,使得每个人距离附近的一棵圣诞树最近,并输出所有人最近距离之和。(每个人每棵树的位置两两不同)

思路

多源广搜,先找距离每棵圣诞树为 $1$ 的位置,然后是距离为 $2$ 的位置...直至找到 $m$ 个。(和 ABC161DUVA - 136 有些类似)

代码

#include <bits/stdc++.h>
using namespace std;
int main() {
    int n, m; cin >> n >> m;
    int x[n]; for (int &i : x) cin >> i;
    map<int, int> d;
    queue<int> q;
    for (int i : x) d[i] = 0, q.push(i);
    long long ans = 0;
    vector<int> res;
    while (!q.empty()) {
        if (res.size() >= m) break;
        int cur = q.front();
        q.pop();
        if (d[cur] != 0) {
            ans += d[cur];
            res.push_back(cur);
        }
        if (!d.count(cur - 1)) {
            d[cur - 1] = d[cur] + 1;
            q.push(cur - 1);
        }
        if (!d.count(cur + 1)) {
            d[cur + 1] = d[cur] + 1;
            q.push(cur + 1);
        }
    }
    cout << ans << "\n";
    for (int i = 0; i < m; i++) cout << res[i] << ' ';
}

E - New Year Parties

题意

数轴的一些点上有一些人,每个点 $x$ 处的每个人可以选择待在原地或移动到 $x - 1$ 或 $x + 1$ 处,一个人最多移动一次,问这些人最少和最多能占据多少点。

思路

最少的点:若当前点 $x$ 有人,则当前点的人可以与 $x + 2$ 处的人都移动到 $x + 1$ 处,然后跳至 $x + 3$ 处继续判断。

最多的点:每个点 $x$ 向左移动一人到 $x-1$,因为这样对后面的点最优,如果有多余的人数可以在保留 $x$ 点的人的前提下再向右移动一人至 $x+1$ 。

代码

#include <bits/stdc++.h>
using namespace std;
int main() {
    int n; cin >> n;
    int cnt[n + 3] = {};
    int a[n]; for (int &i : a) cin >> i, ++cnt[i];
    int mi = 0;
    for (int i = 1; i <= n; i++)
        if (cnt[i]) ++mi, i += 2;
    int mx = 0;
    for (int i = 1; i <= n; i++)
        if (cnt[i]){
            if (!cnt[i - 1]) ++cnt[i - 1], --cnt[i];
            if (cnt[i] > 1)  ++cnt[i + 1], --cnt[i];
        }
    for (int i = 0; i <= n + 1; i++) mx += cnt[i] > 0;
    cout << mi << ' ' << mx;
}

F - DIY Garland

这篇博客已经讲得比较好了,不再赘述。

posted @ 2020-04-29 17:40  Kanoon  阅读(144)  评论(0)    收藏  举报