11.25训练赛

A.P1144 最短路计数

bfs,从样例中可以看出重边算不同路径,注意取模。

#include <bits/stdc++.h>
#define fu(a, b, c) for (ll a = b; a <= c; a++)
#define fd(a, b, c) for (ll a = b; a >= c; a--)
#define dbg(x) cout << #x << '=' << x << ' '
#define mx(a, b) a = max(a, b)
#define mn(a, b) a = min(a, b)
#define f first
#define s second
using namespace std;
using ll = long long;
using pll = pair<ll, ll>;
const ll N = 1e7, M = 100003;
ll t, n, m, k, ans;
ll c[N], d[N], q[N], qf, qb;

int main() {
    ios::sync_with_stdio(0), cin.tie(0);
    cin >> n >> m;
    vector<ll> g[n + 1];
    ll u, v;
    fu(i, 1, m) {
        cin >> u >> v;
        if (u ^ v) {
            g[u].emplace_back(v);
            g[v].emplace_back(u);
        }
    }
    q[qb++] = c[1] = d[1] = 1;
    while (qf ^ qb) {
        u = q[qf++], c[u] %= M;
        for (ll v : g[u]) {
            if (!d[v])
                d[v] = d[u] + 1, q[qb++] = v;
            if (d[u] + 1 == d[v])
                c[v] += c[u];
        }
    }
    fu(i, 1, n) cout << c[i] << '\n';
}

B.P1106 删数问题

相当于取n-k个数字,从左到右贪心,输出要去掉前导0。

n, k = input(), int(input())
m = len(n) - 1
ans, num = '', m - k
p, i, mx = -1, 0, ':'
while i < m:
    if(n[i] < mx):
        p, mx = i, n[i]
    if m - i == num:
        num -= 1
        ans += n[p]
        i, mx = p, ':'
    i += 1
print(int(ans))

C.CF1612E Messages

假设固定了\(x\)条信息,则某条信息的期望为\(\frac{\sum min(x, k_i)}{x}\)
这里\(i = 1, 2, 3...\)代表第\(i\)个被期望阅读该信息的人的\(k\)值,
\(∵k_i <= 20∴x <= 20\)时取到最大值,枚举\(x\)对信息按期望排序即可。

import io
import os
input = io.BytesIO(os.read(0, os.fstat(0).st_size)).readline

N = 200001
n = int(input())
m, k = [0] * n, [0] * n
a = set()
for i in range(n):
    m[i], k[i] = map(int, input().split())
    a.add(m[i])
u, d = 0, 1
for x in range(1, 21):
    s = [0] * N
    for i in range(n):
        s[m[i]] += min(x, k[i])
    a = sorted(a, key=lambda i: s[i], reverse=1)
    S = sum(s[i] for i in a[:x])
    if S * d > u * x:
        u, d = S, x
        ans = a[:x]
print(len(ans))
for i in ans:
    print(i, end=' ')

D.CF1612F Armor and Weapons

\(dp[i][j]\)表示第\(i\)\(armor_j\)可以配对的最大\(weapon\),转移显然,
重点是观察到数值的增长类似斐波那契数列,达到上限后无法增长,即复杂度
\(O(n * (\log n + n / m))\),所以在\(n > m\)时交换\(armor\)\(weapon\)保证复杂度。

import io
import os
from queue import *
input = io.BytesIO(os.read(0, os.fstat(0).st_size)).readline

n, m = map(int, input().split())
f = 0
if n > m:
    n, m, f = m, n, 1
mp, q = {}, int(input())
for _ in range(q):
    a, w = map(int, input().split())
    if f:
        a, w = w, a
    if a in mp:
        mp[a].add(w)
    else:
        mp[a] = set([w])

f = [0] * (n + 1)
f[1], t = 1, 0
while f[n] < m:
    g = f[:]
    for i in range(1, n + 1):
        if f[i]:
            p = f[i] + i + (i in mp and f[i] in mp[i])
            g[min(p, n)] = max(g[min(p, n)], f[i])
            g[i] = max(g[i], min(p, m))
    t += 1
    f = g
print(t)

E.P7815 自傷無色

对于当前根节点不同子树下距离为\(a, b\)的点(\(a \ge b\)),有\(a - b < x < a + b\)
对数量的贡献是\(2b - 1\),对大小的贡献为\((2a + b)(2b - 1)\),通过dsu on tree
或者线段树合并解决。

#include <bits/extc++.h>
#include <bits/stdc++.h>
#define fu(a, b, c) for (ll a = b; a <= c; a++)
#define fd(a, b, c) for (ll a = b; a >= c; a--)
#define dbg(x) cout << #x << '=' << x << ' '
#define mx(a, b) a = max(a, b)
#define mn(a, b) a = min(a, b)
#define f first
#define s second
using namespace std;
using namespace __gnu_pbds;
using ll = long long;
using LL = __int128;
using pll = pair<ll, ll>;
const ll N = 1e5 + 10, M = 1e9 + 7, i2 = M + 1 >> 1;
ll t, n, u, v, w, p, c, val, num;
ll W[N], d[N], sz[N], son[N], T[3][N], s[3];
gp_hash_table<ll, ll> mp;
vector<pll> g[N];

ll inv(ll x) { return x ^ 1 ? -M / x * inv(M % x) % M : 1; }

void upd(ll p, ll x, ll f) {
    while (p <= n) {
        T[0][p] += f, T[1][p] += (2 * x - 1) * f;
        T[2][p] += x * (2 * x - 1) % M * f;
        p += p & -p; // 分别维护前缀个数,2x - 1, x * (2x - 1)
    }
}

void qry(ll p, ll f) {
    while (p) {
        fu(i, 0, 2) s[i] += T[i][p] * f;
        p -= p & -p;
    }
}

void dfs0(ll u, ll f) {
    sz[u] = 1, W[u] = d[u];
    for (auto [v, w] : g[u])
        if (v ^ f) {
            d[v] = d[u] + w, dfs0(v, u), sz[u] += sz[v];
            if (sz[v] > sz[son[u]])
                son[u] = v;
        }
}

void cal(ll u, ll f, ll F, ll w) {
    p = mp[d[u]], t = (d[u] - w) % M;
    if (F) {
        upd(p, d[u] % M, F);
    } else {
        // 计算距离小于等于当前节点的节点的贡献
        s[0] = s[1] = s[2] = 0, qry(p, 1), s[1] %= M, s[2] %= M;
        c = (s[1] - s[0] * 2 * w) % M, num += c;
        // b(2b - 1),b = d[x] - w 代回去推
        val += s[2] + w * ((2 * w - 1) * s[0] % M - 2 * s[1]);
        // 2a(2b - 1), a = d[u] - w
        val = (val + 2 * t * c) % M;
        // 计算比当前节点距离大的节点的贡献
        s[0] = s[1] = 0, qry(p, -1), qry(n, 1), s[1] %= M;
        c = 2 * t - 1, num += c * s[0], val += t * c % M * s[0];
        val = (val + (s[1] + s[0] * (1 - 2 * w)) % M * c) % M;
    }
    for (auto [v, x] : g[u])
        if (v ^ f)
            cal(v, u, F, w);
}

void dfs(ll u, ll f, ll F = 0) {
    for (auto [v, w] : g[u])
        if (v ^ f && v ^ son[u])
            dfs(v, u, 1); // 处理轻儿子,消除影响
    if (son[u])           // 处理重儿子,不消除影响
        dfs(son[u], u, 0), upd(mp[d[son[u]]], d[son[u]] % M, 1);
    for (auto [v, w] : g[u])
        if (v ^ f && v ^ son[u])
            // 先计算贡献再更新,计算时去掉根节点距离
            cal(v, u, 0, d[u] % M), cal(v, u, 1, 0);
    if (F) // 清空影响
        for (auto [v, w] : g[u])
            if (v ^ f)
                cal(v, u, -1, 0);
}

int main() {
    ios::sync_with_stdio(0), cin.tie(0);
    cin >> n;
    fu(i, 2, n) {
        cin >> u >> v >> w;
        g[u].emplace_back(v, w);
        g[v].emplace_back(u, w);
    }
    dfs0(1, 0), sort(W + 1, W + n + 1);   // 标记重儿子
    c = unique(W + 1, W + n + 1) - W - 1; // 把距离离散化
    fu(i, 1, c) mp[W[i]] = i;
    dfs(1, 0), num = (num % M + M) % M;
    cout << (num ? (val * inv(num) % M + M) % M : 0);
}

F.P7814 心の記憶

简单构造。

#include <bits/stdc++.h>
#define fu(a, b, c) for (int a = b; a <= c; a++)
#define fd(a, b, c) for (int a = b; a >= c; a--)
#define mx(a, b) a = max(a, b)
#define mn(a, b) a = min(a, b)
using namespace std;
typedef long long ll;
typedef long double ld;
const ll N = 100, M = 1e9 + 7, inv2 = M + 1 >> 1;
ll t, n, m, k, ans;

int main() {
    ios::sync_with_stdio(0), cin.tie(0);
    cin >> t;
    while (t--) {
        string s;
        cin >> n >> m >> s;
        if (n == m || n == 1 || n == 2 && s[0] ^ s[1])
            cout << "-1\n";
        else {
            bool f = 0;
            fu(i, 1, n - 1) if (s[i] == s[0]) {
                s.insert(i, m - n, s[i] == '1' ? '0' : '1');
                f = 1;
                break;
            }
            if (!f)
                s.insert(2, m - n, s[2] == '1' ? '0' : '1');
            cout << s << '\n';
        }
    }
}

G.P6833 雷雨

观察样例可以发现目标是三源最短路的交点。

#include <bits/stdc++.h>
#define fu(a, b, c) for (int a = b; a <= c; a++)
#define fd(a, b, c) for (int a = b; a >= c; a--)
using namespace std;
typedef long long ll;
const int N = 1000;
int n, m, a, b, c, e[N][N];
short int dx[4] = {0, 0, 1, -1}, dy[4] = {1, -1, 0, 0};
ll d[3][N][N], ans = 1e18;

struct node {
    short int x, y;
    ll d;
    bool operator<(node x) const { return d > x.d; }
};

void dfs(int i, int j, int k) {
    priority_queue<node> q;
    q.push({i, j, e[i][j]});
    d[k][i][j] = e[i][j];
    while (!q.empty()) {
        node no = q.top();
        int i = no.x, j = no.y;
        ll dis = no.d;
        q.pop();
        fu(l, 0, 3) {
            int x = i + dx[l], y = j + dy[l];
            if (x >= 0 && x <= n - 1 && y >= 0 && y <= m - 1 &&
                dis + e[x][y] < d[k][x][y]) {
                d[k][x][y] = dis + e[x][y];
                q.push({x, y, dis + e[x][y]});
            }
        }
    }
}

int main() {
    ios::sync_with_stdio(0), cin.tie(0);
    cin >> n >> m >> a >> b >> c;
    fu(i, 0, n - 1) fu(j, 0, m - 1) cin >> e[i][j];
    memset(d, 0x3f, sizeof d), dfs(0, a - 1, 0);
    dfs(m - 1, b - 1, 1), dfs(m - 1, c - 1, 2);
    fu(i, 0, n - 1) fu(j, 0, m - 1) {
        ll tmp = 0;
        fu(k, 0, 2) tmp += d[k][i][j];
        tmp -= 2 * e[i][j];
        ans = min(ans, tmp);
    }
    cout << ans;
    return 0;
}

H.P3180 地图

https://www.cnblogs.com/lemu/p/15227942.html C题。

posted @ 2021-12-02 14:53  lemu  阅读(55)  评论(0编辑  收藏  举报
4