Educational Codeforces Round 100 (Rated for Div. 2)

Educational Codeforces Round 100 (Rated for Div. 2)

A

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

#define int long long

signed main()
{
    ios::sync_with_stdio(false);
    int t;
    cin >> t;
    while (t--)
    {
        int a, b, c;
        cin >> a >> b >> c;
        int mn = 1e18, res = 0;
        mn = min(a, min(b, c));
        res += a + b + c - 3 * mn;
        if (res <= 6 * mn + 6 && (a + b + c) % 9 == 0)
            cout << "YES" << endl;
        else
            cout << "NO" << endl;
    }
}

B

交替着,一个取原数,一个取 1


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

#define int long long

signed main()
{
    ios::sync_with_stdio(false);
    int t;
    cin >> t;
    while (t--)
    {
        int n;
        cin >> n;
        vector<int> a(n + 2);
        vector<int> s(4);
        for (int i = 1; i <= n; i++)
        {
            cin >> a[i];
            s[2 - (i & 1)] += a[i];
        }
        for (int i = 1; i <= n; i++)
        {
            cout << ((i % 2) == (s[1] > s[2])
                         ? a[i]
                         : 1)
                 << " ";
        }
        cout << endl;
    }
}

[CF1463C] Busy Robot

Description

机器人在一维坐标轴上移动。你可以给这个机器人下达指令,指令的形式为 (t_i), (x_i) ,意味着机器人在第 (t_i) 秒的时候获得一条指令,此时这个机器人以 (1/s) 的速度从现在的位置开始向 (x_i) 移动。若机器人执行当前指令的过程中收到其他命令那么忽略。现在问你给出的指令中被成功执行的命令有几条,条件为:假设当前命令为 t_i, x_i , 若机器人在 t_i 到 t_{i+1}这个时间区间(包括边界)内到达过 x_i 这个位置,则称这条命令被成功执行。

Solution

我们始终维护当前的目标位置,对于一个命令,我们先判断是否能接受它(即当前是否以及处于当前目标位置,如果不等于则需要继续向着这个目标走,否则,我们就用新的命令的目标替换当前目标),然后我们通过当前时间和下面一条命令进来的时间之间的差值来判断这条命令能否被完成

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

#define int long long

signed main()
{
    ios::sync_with_stdio(false);
    int t;
    cin >> t;
    while (t--)
    {
        int n;
        cin >> n;

        vector<pair<int, int>> vec(n + 2);
        for (int i = 1; i <= n; i++)
            cin >> vec[i].first >> vec[i].second;

        int current_time = -1;
        int current_target = 0;
        int current_pos = 0;

        vec[n + 1].first = 1e12;
        vec[n + 1].second = 0;

        vector<int> fin(n + 2);

        for (int i = 1; i <= n; i++)
        {
            // cout << "time = " << vec[i].first << " pos=" << current_pos << endl;
            auto [new_time, new_target] = vec[i];
            int succ_flag = 0;
            if (current_target == current_pos) // accept
            {
                current_target = new_target;
                succ_flag = 1;
            }
            int step = min(vec[i + 1].first - vec[i].first, abs(current_pos - current_target));
            int current_pos_ = current_pos;
            if (current_pos < current_target)
                current_pos_ += step;
            else
                current_pos_ -= step;
            if ((((current_pos <= new_target) && (current_pos_ >= new_target) && current_pos <= current_pos_) ||
                 ((current_pos_ <= new_target) && (current_pos >= new_target) && current_pos_ <= current_pos)))
            {
                fin[i] = 1;
            }
            current_pos = current_pos_;
        }

        int ans = 0;
        for (int i = 1; i <= n; i++)
            ans += fin[i];

        cout << ans << endl;
    }
}

[CF1463D] Pairs - 贪心

Description

你有 (2n) 个整数 (1,2,cdots,2n),你需要将其分成 (n) 对,然后选择其中 (x) 对,取出其中的较小数,并取出其余 (n-x) 对中的较大数,使得最终取出的数组成的集合为 ({b_1,b_2,cdots,b_n})。问有多少个满足题意的 (x)

Solution

贪心,有点类似用栈做括号匹配

把所有选中的数变成 1,没选中的变成 0

从左往右扫描

第一遍,碰到 0 积累,碰到 1 就消 0,没得消就废

第二遍,碰到 1 积累,碰到 0 就消 1,没得消就废

两次答案夹的整数区间长度就是答案

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

#define int long long

signed main()
{
    ios::sync_with_stdio(false);
    int t;
    cin >> t;
    while (t--)
    {
        int n;
        cin >> n;

        vector<int> a(2 * n + 2);
        for (int i = 1; i <= n; i++)
        {
            int x;
            cin >> x;
            a[x]++;
        }

        int ans0 = 0, ans1 = 0, cnt0 = 0, cnt1 = 0;
        for (int i = 1; i <= 2*n; i++)
        {
            if (a[i])
            {
                if (cnt0 > 0)
                    cnt0--, ans1++;
                cnt1++;
            }
            else
            {
                if (cnt1 > 0)
                    cnt1--, ans0++;
                cnt0++;
            }
        }

        ans1 = n - ans1;
        cout << abs(ans1 - ans0) + 1 << endl;
    }
}

[CF1463E] Plan of Lectures - 拓扑排序,并查集

Description

构造一个 1..n 的排列,有一些限制:指定了一些 (ai,i) 要求 ai 出现在 i 的前面,指定了一些 (i,j) 要求 i 一定在 j 之前一个位置

Solution

先考虑第二类条件,用类似并查集的方法来串串,最后我们把一个点往后几个固定的点都找出来,同时判断是否有环路

接下来缩点(选取链头作为代表点)然后跑拓扑排序

跑完拓扑以后,我们把得到的序列展开(缩点还原),然后检查一遍所有条件是否满足即可

(第一遍写的时候把两种条件看反了)

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

#define int long long
const int N = 1000005;
int n, m;
int fa[N];
pair<int, int> e[N];
vector<int> toposeq;
vector<int> g[N];
int vis[N], ind[N];
list<int> ls[N];
vector<int> seq;
int a[N];

int find(int p)
{
    return p == fa[p] ? p : fa[p] = find(fa[p]);
}

void dfs(int p)
{
    vis[p] = 1;
    for (auto q : g[p])
        if (vis[q] == 0)
        {
            dfs(q);
        }
    toposeq.push_back(p);
}

signed main()
{
    ios::sync_with_stdio(false);
    cin >> n >> m;
    for (int i = 1; i <= n; i++)
        fa[i] = i, ls[i].push_back(i);
    for (int i = 1; i <= n; i++)
    {
        cin >> a[i];
    }
    for (int i = 1; i <= m; i++)
    {
        int u, v;
        cin >> u >> v;
        int p = find(u), q = find(v);
        if (p == q)
        {
            cout << 0 << endl;
            return 0;
        }
        else
        {
            fa[q] = p;
            ls[p].splice(ls[p].end(), ls[q]);
        }
    }
    for (int i = 1; i <= n; i++)
    {
        if (a[i] == 0)
            continue;
        int u = a[i], v = i;
        e[i] = {u, v};
        if (find(u) == find(v))
            continue;
        g[find(u)].push_back(find(v));
        ind[find(v)]++;
    }
    for (int i = 1; i <= n; i++)
        if (ind[i] == 0 && find(i) == i)
            dfs(i);
    reverse(toposeq.begin(), toposeq.end());
    for (auto p : toposeq)
    {
        for (auto i : ls[p])
        {
            seq.push_back(i);
        }
    }
    vector<int> inv(n + 2);
    for (int i = 0; i < seq.size(); i++)
        inv[seq[i]] = i;
    for (int i = 1; i <= n; i++)
    {
        if (a[i] == 0)
            continue;
        int u = a[i], v = i;
        if (inv[v] < inv[u])
        {
            cout << 0 << endl;
            return 0;
        }
    }
    if (seq.size() == 0)
    {
        cout << 0 << endl;
        return 0;
    }
    for (int i = 0; i < seq.size(); i++)
        cout << seq[i] << " ";
    cout << endl;
}
原文地址:https://www.cnblogs.com/mollnn/p/14474792.html