T1:First Player

模拟

代码实现
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (n); ++i)

using namespace std;

int main() {
    int n;
    cin >> n;
    
    vector<string> s(n);
    vector<int> a(n);
    rep(i, n) cin >> s[i] >> a[i];
    
    int si = 0;
    rep(i, n) if (a[i] < a[si]) si = i;
    
    rep(i, n) {
        int ni = (si+i)%n;
        cout << s[ni] << '\n';
    }
    
    return 0;
}

T2:Subscribers

模拟

代码实现
#include <bits/stdc++.h>

using namespace std;

int main() {
    int n;
    cin >> n;
    
    string s = to_string(n);
    for (int i = 3; i < s.size(); ++i) {
        s[i] = '0';
    }
    
    cout << s << '\n';
    
    return 0;
}

T3:Virus

可以将满足欧几里得距离不超过 \(d\) 的两点进行连边,在点 \(1\) 所在的连通分量内的点都会被感染

可以用 dfs/bfs/并查集 实现

代码实现
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (n); ++i)

using namespace std;

int main() {
    int n, d;
    cin >> n >> d;
    
    vector<int> x(n), y(n);
    rep(i, n) cin >> x[i] >> y[i];
    
    auto near = [&](int a, int b) {
        int dx = x[a]-x[b];
        int dy = y[a]-y[b];
        return dx*dx+dy*dy <= d*d;
    };
    
    queue<int> q;
    vector<bool> ans(n);
    ans[0] = true; q.push(0);
    while (q.size()) {
        int v = q.front(); q.pop();
        rep(u, n) {
            if (near(v, u)) {
                if (ans[u]) continue;
                ans[u] = true;
                q.push(u);
            }
        }
    }
    
    rep(i, n) {
        puts(ans[i] ? "Yes" : "No");
    }
    
    return 0;
}

T4:A Piece of Cake

先用两次 std::lower_bound() 来确定每个草莓位于哪块区域
再用 std::map<pair<int, int>, int> 来统计每块区域中草莓的个数
然后遍历一遍 map,找到 \(m\)\(M\)

注意:当 map 的大小 \(< (A+1)(B+1)\) 时,\(m = 0\)

代码实现
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (n); ++i)

using namespace std;
using ll = long long;
using P = pair<int, int>;

int main() {
    int w, h, n;
    cin >> w >> h >> n;
    
    vector<int> p(n), q(n);
    rep(i, n) cin >> p[i] >> q[i];
    
    int A;
    cin >> A;
    vector<int> a(A);
    rep(i, A) cin >> a[i];
    int B;
    cin >> B;
    vector<int> b(B);
    rep(i, B) cin >> b[i];
    
    map<P, int> mp;
    rep(i, n) {
        int x = lower_bound(a.begin(), a.end(), p[i])-a.begin();
        int y = lower_bound(b.begin(), b.end(), q[i])-b.begin();
        mp[P(x, y)]++;
    }
    
    int m = n, M = 0;
    for (auto e : mp) {
        m = min(m, e.second);
        M = max(M, e.second);
    }
    if (mp.size() < (ll)(A+1)*(B+1)) m = 0;
    
    cout << m << ' ' << M << '\n';
    
    return 0;
}

T5:Good Graph

可以用并查集来维护图 \(G\) 所在的连通分量
对于这 \(K\) 对点 \((x, y)\),需要记录 \(x\)\(y\) 分别位于哪个连通分量
num[x] 表示 \(x\) 所在的连通分量的编号
std::set<pair<int, int>> 来维护 \((\operatorname{num[x]}, \operatorname{num}[y])\),并判断 \((\operatorname{num[p]}, \operatorname{num}[q])\) 是否在 std::set

特别地,这里可以直接将 \(x\) 所在的连通分量的根节点作为 num[x]

代码实现
#include <bits/stdc++.h>
#if __has_include(<atcoder/all>)
#include <atcoder/all>
using namespace atcoder;
#endif
#define rep(i, n) for (int i = 0; i < (n); ++i)

using namespace std;
using P = pair<int, int>;

int main() {
    int n, m;
    cin >> n >> m;
    
    dsu uf(n);
    rep(i, m) {
        int a, b;
        cin >> a >> b;
        --a; --b;
        uf.merge(a, b);
    }
    
    int k;
    cin >> k;
    set<P> st;
    rep(i, k) {
        int a, b;
        cin >> a >> b;
        --a; --b;
        a = uf.leader(a);
        b = uf.leader(b);
        if (a > b) swap(a, b);
        st.emplace(a, b);
    }
    
    int q;
    cin >> q;
    rep(i, q) {
        int a, b;
        cin >> a >> b;
        --a; --b;
        a = uf.leader(a);
        b = uf.leader(b);
        if (a > b) swap(a, b);
        if (st.count(P(a, b))) puts("No");
        else puts("Yes");
    }
    
    return 0;
}

T6:Shift Table

先考虑固定 \(M\) 的问题
比如 \(M = 7\),那么青木可以在高桥都来的星期几可以休息,否则就必须出勤,这样就很容易求出轮班的个数
还有,如果 \(M'\)\(M\) 的倍数,那么 "\(M'\) 周期的轮班表"就包含了所有“\(M\) 周期的轮班表”,只需容斥一下重复的即可

代码实现
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (n); ++i)

using namespace std;

int main() {
    int n;
    cin >> n;
    
    vector<string> s(n);
    vector<int> a(n);
    rep(i, n) cin >> s[i] >> a[i];
    
    int si = 0;
    rep(i, n) if (a[i] < a[si]) si = i;
    
    rep(i, n) {
        int ni = (si+i)%n;
        cout << s[ni] << '\n';
    }
    
    return 0;
}