2021CCPC桂林

B

题意:1e6位a+b=c算式。每次修改某个加数的某一位,求这一位修改后的值和算式改变的位数。

题解:用set维护 \(a_i+b_i\neq 9\) 的位置,这样修改后的修改位的值和改变的位数都可以通过它算出来,然后每次修改至多往set插入或删除一个元素。

//
// Created by blackbird on 2023/11/16.
//
#pragma GCC optimize("Ofast")
#include <bits/stdc++.h>
using namespace std;

signed main() {
    cin.tie(nullptr)->sync_with_stdio(false);

    int n, q; cin >> n >> q;
    string s0, s1; cin >> s0 >> s1;

    set<int> s;
    vector<int> a[2] = {vector<int>(n + 1), vector<int>(n + 1)};
    for (int i = 1; i <= n; i++) {
        a[0][i] = s0[i - 1] - '0';
        a[1][i] = s1[i - 1] - '0';
        if (a[0][i] + a[1][i] != 9)
            s.insert(i);
    }

    while (q--) {
        int r, c, d; cin >> r >> c >> d; r--;
        auto it = s.upper_bound(c);
        int carry = it != s.end() && a[0][*it] + a[1][*it] >= 10;
        int pre = a[0][c] + a[1][c] + carry;
        a[r][c] = d;
        int now = a[0][c] + a[1][c] + carry;
        cout << now % 10 << " ";

        if (pre == now) cout << "0\n";
        else if ((pre < 10) != (now < 10)) {
            it = s.lower_bound(c);
            int prec = it == s.begin() ? 0 : *prev(it) - 1;
            cout << 1 + (c - prec) << "\n";
        } else cout << "2\n";

        if (a[0][c] + a[1][c] != 9) s.insert(c);
        else s.erase(c);
    }
    return 0;
}

K

题意:求1号点到各节点的最小费用最短路。每条边属于一个集合,第k次走集合t的边花费\(k\cdot w_t\)\(n\le50\)

题解:

bfs求出最短路数组d,则(u,v)在最短路中的条件是d[v]=d[u]+1。

神奇的是,可以证明最短路径数量不会超过 \(3^{n/3}\) (考虑 \(k^{n/k}\) 最大值),搜索所有最短路即可。

//
// Created by blackbird on 2023/11/16.
//
#pragma GCC optimize("Ofast")
#include <bits/stdc++.h>
#define pii pair<int,int>
using namespace std;

signed main() {
    cin.tie(nullptr)->sync_with_stdio(false); srand(time(0));

    int n, m; cin >> n >> m;
    vector<vector<pii>> g(n + 1);
    vector<int> w(m + 1), c(m + 1);

    for (int i = 1; i <= m; i++) cin >> w[i];
    for (int i = 1; i <= m; i++) {
        int u, v; cin >> u >> v >> c[i];
        g[u].push_back({v, i}); g[v].push_back({u, i});
    }

    vector<int> d(n + 1, -1);
    d[1] = 0;
    queue<int> q; q.push(1);
    while (!q.empty()) {
        int u = q.front(); q.pop();
        for (auto [v, edge] : g[u]) {
            if (d[v] != -1) continue;
            d[v] = d[u] + 1;
            q.push(v);
        }
    }

    vector<int> ans(n + 1, 1e9);
    vector<int> cnt(m + 1);
    auto dfs = [&](auto self, int u, int sum) -> void {
        for (auto [v, edge] : g[u]) {
            if (d[v] == d[u] + 1) {
                int nsum = sum + (cnt[c[edge]] + 1) * w[c[edge]];
                ans[v] = min(ans[v], nsum);
                cnt[c[edge]]++;
                self(self, v, nsum);
                cnt[c[edge]]--;
            }
        }
    };
    dfs(dfs, 1, 0);

    for (int i = 2; i <= n; i++) cout << ans[i] << "\n";
    return 0;
}
posted @ 2023-11-16 23:25  _vv123  阅读(20)  评论(0编辑  收藏  举报