T1:Penalty Kick

模拟

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

using namespace std;

int main() {
    int n;
    cin >> n;
    
    string ans;
    for (int i = 1; i <= n; ++i) {
        if (i%3 == 0) ans += 'x';
        else ans += 'o';
    }
    
    cout << ans << '\n';
    
    return 0;
}

T2:Farthest Point

暴力枚举

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

using namespace std;

int pow2(int x) { return x*x; }

int main() {
    int n;
    cin >> n;
    
    vector<int> x(n), y(n);
    rep(i, n) cin >> x[i] >> y[i];
    
    rep(i, n) {
        int dmax = -1, ans = -1;
        rep(j, n) {
            int d = pow2(x[i]-x[j]) + pow2(y[i]-y[j]);
            if (dmax < d) {
                dmax = d;
                ans = j;
            }
        }
        cout << ans+1 << '\n';
    }
    
    return 0;
}

T3:Colorful Beans

可以用 map 维护每种颜色中的美味度最小的豆子

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

using namespace std;

int main() {
    int n;
    cin >> n;
    
    unordered_map<int, int> d;
    rep(i, n) {
        int a, c;
        cin >> a >> c;
        if (d.count(c)) d[c] = min(d[c], a);
        else d[c] = a;
    }
    
    int ans = 0;
    for (auto p : d) ans = max(ans, p.second);
    
    cout << ans << '\n';
    
    return 0;
}

T4:Medicines on Grid

可以将每个体力药水向其他体力药水以及起点和终点加边,而能否加边取决于从当前体力药水所在的位置出发到达其他体力药水以及起点和终点的最短距离不应超过当前体力药水的能量,可以用bfs实现
建完图后,从起点出发再跑一遍bfs即可

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

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

struct Med {
    int r, c, e;
    Med() {}
    Med(int r, int c, int e): r(r), c(c), e(e) {}
};

const int INF = 1001001001;

const int di[] = {-1, 0, 1, 0};
const int dj[] = {0, 1, 0, -1};

int main() {
    int h, w;
    cin >> h >> w;
    
    vector<string> s(h);
    rep(i, h) cin >> s[i];
    
    int si = 0, sj = 0, ti = 0, tj = 0;
    rep(i, h)rep(j, w) {
        if (s[i][j] == 'S') si = i, sj = j;
        if (s[i][j] == 'T') ti = i, tj = j;
    }
    
    int n;
    cin >> n;
    vector<Med> meds;
    rep(i, n) {
        int r, c, e;
        cin >> r >> c >> e;
        --r; --c;
        meds.emplace_back(r, c, e);
    }
    meds.emplace_back(si, sj, 0);
    meds.emplace_back(ti, tj, 0);
    n += 2;
    int smi = n-2, tmi = n-1;
    
    vector<vector<int>> to(n);
    rep(sv, n) {
        auto [sr, sc, se] = meds[sv];
        vector dist(h, vector<int>(w, INF));
        queue<P> q;
        dist[sr][sc] = 0; q.emplace(sr, sc);
        while (q.size()) {
            auto [i, j] = q.front(); q.pop();
            rep(v, 4) {
                int ni = i+di[v], nj = j+dj[v];
                if (ni < 0 or nj < 0 or ni >= h or nj >= w) continue;
                if (s[ni][nj] == '#') continue;
                if (dist[ni][nj] != INF) continue;
                dist[ni][nj] = dist[i][j]+1;
                q.emplace(ni, nj);
            }
        }
        
        rep(v, n) if (v != sv) {
            auto [r, c, e] = meds[v];
            if (dist[r][c] <= se) to[sv].push_back(v);
        }
    }
    
    vector<int> dist(n, INF);
    queue<int> q;
    dist[smi] = 0; q.push(smi);
    while (q.size()) {
        int v = q.front(); q.pop();
        for (int u : to[v]) {
            if (dist[u] != INF) continue;
            dist[u] = dist[v]+1;
            q.push(u);
        }
    }
    
    if (dist[tmi] != INF) puts("Yes");
    else puts("No");
    
    return 0;
}

T5:Minimize Sum of Distances

这题本质上就是找带权树的重心

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

using namespace std;
using ll = long long;

int main() {
    int n;
    cin >> n;
    
    vector<vector<int>> to(n);
    rep(i, n-1) {
        int a, b;
        cin >> a >> b;
        --a; --b;
        to[a].push_back(b);
        to[b].push_back(a);
    }
    
    vector<int> c(n);
    rep(i, n) cin >> c[i];
    
    ll tot = 0;
    rep(i, n) tot += c[i];
    
    int x = -1;
    {
        auto dfs = [&](auto& f, int v, int p=-1) -> ll {
            ll res = c[v];
            ll mx = 0;
            for (int u : to[v]) {
                if (u == p) continue;
                ll now = f(f, u, v);
                mx = max(mx, now);
                res += now;
            }
            mx = max(mx, tot-res);
            if (mx*2 <= tot) x = v;
            return res;
        };
        dfs(dfs, 0);
    }
    
    ll ans = 0;
    auto dfs = [&](auto& f, int v, int dist=0, int p=-1) -> void {
        ans += (ll)dist*c[v];
        for (int u : to[v]) {
            if (u == p) continue;
            f(f, u, dist+1, v);
        }
    }; 
    dfs(dfs, x);
    
    cout << ans << '\n';
    
    return 0;
}

T6:Oddly Similar

挺无聊的一道题,暴力加上火车头就可以跑的很快

正解做法是用 bitset 优化

代码实现
#pragma GCC optimize ("O3")
#pragma GCC optimize ("unroll-loops")
#pragma GCC target ("avx2")
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (n); ++i)

using namespace std;

int main() {
    cin.tie(nullptr) -> sync_with_stdio(false);
    
    int n, m;
    cin >> n >> m;
    
    vector a(n, vector<int>(m));
    rep(i, n)rep(j, m) cin >> a[i][j];
    
    using BS = bitset<2000>;
    vector<BS> d(n);
    rep(k, m) {
        map<int, vector<int>> is;
        rep(i, n) is[a[i][k]].push_back(i);
        BS x;
        for (auto p : is) {
            for (int i : p.second) x[i] = 1;
            for (int i : p.second) d[i] ^= x;
            for (int i : p.second) x[i] = 0;
        }
    }
    
    int ans = 0;
    rep(i, n)rep(j, i) ans += d[i][j];
    
    cout << ans << '\n';
    
    return 0;
}

T7:Max (Sum - Max)

决策单调性分治,代价函数可以用主席树来处理