371

A - Jiro

有三兄弟,分别叫 ABC。他们之间的年龄关系由三个字符 SAB,SAC,SBC 表示,其含义如下:

谁是中间的哥哥,也就是三个哥哥中的老二?

void solve() {
    char a, b, c;cin >> a >> b >> c;
    if (b == '<' && c == '>' || b == '>' && c == '<') {
        cout << "C\n";
    } else if (b == '<' && a == '>' || b == '>' && a == '<') {
        cout << "A\n";
    } else {
        cout << "B\n";
    }
}

B - Taro

在 AtCoder 王国,长子的名字总是太郎。其他人都不叫太郎。长子是每个家庭中最早出生的男孩子。

王国共有 N 个家庭,出生了 M 个婴儿。在 M 个婴儿出生之前, N 个家庭都没有婴儿出生。

婴儿的信息按出生时间顺序排列。

出生在 Ai 家庭的 i 个婴儿,如果 Bi 为 "M",则该婴儿为男性;如果为 "F",则该婴儿为女性。

请判断 M 个婴儿的名字是否叫太郎。

void solve() {
    int n, m;cin >> n >> m;
    vector<int> a(n + 1);
    for (int i = 1;i <= m;i++) {
        int x;char gen;cin >> x >> gen;
        if (!a[x] && gen == 'M') {
            cout << "Yes\n";a[x] = 1;
        } else {
            cout << "No\n";
        }
    }
}

C - Make Isomorphic

给你简单的无向图 GH ,每个图都有 N 个顶点:顶点 12N 。图 GMG 条边,它的 i -th 边为 (1iMG)

连接顶点 uivi 。图 HMH 条边,它的 i -th 边 (1iMH) 连接顶点 aibi

您可以在图 H 上执行以下操作,次数不限,可能为零。

求使 GH 同构 所需的最小总成本。

暴力搜索即可

void solve() {
    int n;cin >> n;
    vector<int> p(n + 1);
    iota(p.begin() + 1, p.end(), 1);
    int m;cin >> m;
    vector<pair<int, int>> g1;
    for (int i = 1;i <= m;i++) {
        int u, v;cin >> u >> v;g1.push_back({u,v});
    }
    int h;cin >> h;
    set<pair<int, int>>s2;
    for (int i = 1;i <= h;i++) {
        int u, v;cin >> u >> v;
        s2.insert({u,v});
    }
    vector<vector<int>> val(n + 1, vector<int>(n + 1));
    for (int i = 1;i < n;i++) {
        for (int j = i + 1;j <= n;j++) {
            cin >> val[i][j];
        }
    }
    int ans = 1e9;
    do {
        set<pair<int, int>> s1;
        for (auto [x, y] : g1) {
            int l = p[x], ll = p[y];
            if (l > ll)swap(l, ll);
            s1.insert({l,ll});
        }
        int sum = 0;
        for (auto [u, v] : s1) {
            if (!s2.count({u, v})) {
                sum += val[u][v];
            }
        }
        for (auto [u, v] : s2) {
            if (!s1.count({u, v})) {
                sum += val[u][v];
            }
        }
        ans = min(ans, sum);
    } while (next_permutation(p.begin() + 1, p.end()));
    cout << ans << '\n';
}

D - 1 D Country

在一条数线上有 N 个村庄。第 i 个村庄位于坐标 Xi 处,有 Pi 个村民。

回答 Q 个问题。 i th 查询的格式如下:

#define int long long
void solve() {
    int n;cin >> n;
    vector<int> x(n + 2), p(n + 1);
    for (int i = 1;i <= n;i++)cin >> x[i];
    x[0] = -1e9 - 1;x[n + 1] = 1e9 + 1;
    for (int i = 1;i <= n;i++)cin >> p[i];
    partial_sum(p.begin() + 1, p.end(), p.begin() + 1);
    int q;cin >> q;
    while (q--) {
        int l, r;cin >> l >> r;
        int a = lower_bound(x.begin(), x.end(), l) - x.begin();
        int b = upper_bound(x.begin(), x.end(), r) - x.begin() - 1;
        cout << p[b] - p[a - 1] << '\n';
    }
}

E - I Hate Sigma Problems

给你一个长度为 N 的整数序列 A=(A1,A2,,AN) 。定义 f(l,r) 为:

计算下面的表达式

i=1Nj=iNf(i,j) .

void solve() {
    int n;cin >> n;
    vector<int> a(n + 1), lst(n + 1, 0);
    int ans = 0;
    for (int i = 1;i <= n;i++) {
        cin >> a[i];
        ans += (i - lst[a[i]]) * lst[a[i]];
        lst[a[i]] = i;
    }
    for (int i = 1;i <= n;i++) {
        ans += (n + 1 - lst[i]) * lst[i];
    }
    cout << ans << '\n';
}

F - Takahashi in Narrow Road

有一条东西向延伸的路,路上有 N 人。这条路从一个叫做原点的点向东西两边无限延伸。

i(1iN) 人最初位于离原点向东 Xi 米的位置。

这些人可以沿着道路向东或向西移动。具体来说,他们可以进行以下任意次数的移动。

他们总共有 Q 个任务,其中 i 个任务 (1iQ) 如下。

求按顺序完成所有 Q 任务所需的最小总移动次数。

Solution

咋一看有点像前缀和,但想到要动态变化,显然就是线段树。

挖坑...

jiangly 的代码:

#include <bits/stdc++.h>

using i64 = long long;
using u64 = unsigned long long;
using u32 = unsigned;

int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    
    int N;
    std::cin >> N;
    
    std::vector<int> X(N);
    std::map<int, int> f;
    for (int i = 0; i < N; i++) {
        std::cin >> X[i];
        X[i] -= i;
        f[i] = X[i];
    }
    
    i64 ans = 0;
    
    int Q;
    std::cin >> Q;
    
    while (Q--) {
        int T, G;
        std::cin >> T >> G;
        T--;
        G -= T;
        
        auto it = std::prev(f.upper_bound(T));
        int x = it->second;
        
        if (x < G) {
            f[T] = x;
            it = f.find(T);
            while (true) {
                auto nxt = std::next(it);
                if (nxt == f.end()) {
                    ans += 1LL * (N - T) * (G - x);
                    x = G;
                    break;
                }
                if (nxt->second >= G) {
                    ans += 1LL * (nxt->first - T) * (G - x);
                    x = G;
                    break;
                }
                ans += 1LL * (nxt->first - T) * (nxt->second - x);
                x = nxt->second;
                f.erase(nxt);
            }
            it->second = x;
        } else {
            if (T + 1 < N && next(it) == f.end() || std::next(it)->first != T + 1) {
                f[T + 1] = x;
            }
            int p = it->first;
            while (true) {
                if (it == f.begin()) {
                    ans += 1LL * (T + 1) * (x - G);
                    x = G;
                    break;
                }
                auto prv = std::prev(it);
                if (prv->second <= G) {
                    ans += 1LL * (T + 1 - p) * (x - G);
                    x = G;
                    break;
                }
                ans += 1LL * (T + 1 - p) * (x - prv->second);
                x = prv->second;
                p = prv->first;
                f.erase(prv);
            }
            f.erase(it);
            f[p] = x;
        }
    }
    
    std::cout << ans << "\n";
}