一题多解

P1073 [NOIP 2009 提高组] 最优贸易

P1073 [NOIP 2009 提高组] 最优贸易

SCC

#include <bits/stdc++.h>

using i64 = long long;

struct SCC {
    int n;
    std::vector<std::vector<int>> adj;
    std::vector<int> stk;
    std::vector<int> dfn, low, bel;
    int cur, cnt;
    
    SCC() {}
    SCC(int n) {
        init(n);
    }
    
    void init(int n) {
        this->n = n;
        adj.assign(n, {});
        dfn.assign(n, -1);
        low.resize(n);
        bel.assign(n, -1);
        stk.clear();
        cur = cnt = 0;
    }
    
    void addEdge(int u, int v) {
        adj[u].push_back(v);
    }
    
    void dfs(int x) {
        dfn[x] = low[x] = cur++;
        stk.push_back(x);
        
        for (auto y : adj[x]) {
            if (dfn[y] == -1) {
                dfs(y);
                low[x] = std::min(low[x], low[y]);
            } else if (bel[y] == -1) {
                low[x] = std::min(low[x], dfn[y]);
            }
        }
        
        if (dfn[x] == low[x]) {
            int y;
            do {
                y = stk.back();
                bel[y] = cnt;
                stk.pop_back();
            } while (y != x);
            cnt++;
        }
    }
    
    std::vector<int> work() {
        // for (int i = 0; i < n; i++) {
        //     if (dfn[i] == -1) {
        //         dfs(i);
        //     }
        // }
        dfs(0);
        return bel;
    }
};

int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);

    int n, m;
    std::cin >> n >> m;

    std::vector<int> a(n);
    for (int i = 0; i < n; ++i) {
        std::cin >> a[i];
    }

    SCC g(n);

    for (int i = 0, u, v, t; i < m; ++i) {
        std::cin >> u >> v >> t;
        --u, --v;
        g.addEdge(u, v);
        if (t == 2) {
            g.addEdge(v, u);
        }
    }

    g.work();

    int N = g.cnt;

    constexpr int inf = 1E9;
    std::vector<int> f0(N, inf), f1(N);
    for (int i = 0; i < n; ++i) {
        int j = g.bel[i];
        if (j == -1) {
            continue;
        }
        f0[j] = std::min(f0[j], a[i]);
        f1[j] = std::max(f1[j], a[i]);
    }

    std::vector<std::vector<int>> adj(N);
    std::vector<int> d(N);

    for (int i = 0; i < n; ++i) {
        for (auto v : g.adj[i]) {
            int x = g.bel[i], y = g.bel[v];
            if (x == y || x == -1 || y == -1) {
                continue;
            }
            adj[x].push_back(y);
            ++d[y];
        }
    }
    
    std::vector<int> dp(N);

    std::queue<int> q;
    q.push(g.bel[0]);

    int ans = 0;
    while (!q.empty()) {
        auto u = q.front();
        q.pop();
        
        dp[u] = std::max(dp[u], f1[u] - f0[u]);

        for (auto v : adj[u]) {
            f0[v] = std::min(f0[v], f0[u]);
            dp[v] = std::max(dp[u], dp[v]);
            if (--d[v] == 0) {
                q.push(v);
            }
        }
    }
    
    std::cout << dp[g.bel[n - 1]] << "\n";
}

分层图

image

#include <bits/stdc++.h>

using i64 = long long;

int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);

    int n, m;
    std::cin >> n >> m;

    std::vector<int> a(n);
    for (int i = 0; i < n; ++i) {
        std::cin >> a[i];
    }

    std::vector<std::vector<std::pair<int, int>>> adj(3 * n);

    auto addEdge = [&](int u, int v) {
        adj[u].push_back({v, 0});
        adj[u + n].push_back({v + n, 0});
        adj[u + 2 * n].push_back({v + 2 * n, 0});
    };

    for (int i = 0, u, v, t; i < m; ++i) {
        std::cin >> u >> v >> t;
        --u, --v;
        addEdge(u, v);
        if (t == 2) {
            addEdge(v, u);
        }
    }

    for (int u = 0; u < n; ++u) {
        adj[u].push_back({u + n, -a[u]});
        adj[u + n].push_back({u + 2 * n, a[u]});
    }

    constexpr int inf = 1E9;
    std::vector<int> dist(3 * n, -inf);
    auto spfa = [&]() -> void {
        std::vector<bool> st(3 * n);
        std::queue<int> q;
        q.push(0);
        st[0] = true;
        dist[0] = 0;

        while (!q.empty()) {
            auto u = q.front();
            q.pop();
    
            st[u] = false;
        
            for (auto [v, w] : adj[u]) {
                if (dist[v] >= dist[u] + w) {
                    continue;
                }
                dist[v] = dist[u] + w;
                if (!st[v]) {
                    st[v] = true;
                    q.push(v);
                }
            }
        }
    };
    spfa();

    std::cout << std::max(dist.back(), 0) << "\n";
}s

反图

后面最大 - 前面最小
两次SPFA

#include <bits/stdc++.h>

using i64 = long long;

int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);

    int n, m;
    std::cin >> n >> m;

    std::vector<int> a(n);
    for (int i = 0; i < n; ++i) {
        std::cin >> a[i];
    }

    std::vector<std::vector<int>> g(n), rg(n);
    for (int i = 0, u, v, t; i < m; ++i) {
        std::cin >> u >> v >> t;
        --u, --v;
        g[u].push_back(v);
        rg[v].push_back(u);
        if (t == 2) {
            g[v].push_back(u);
            rg[u].push_back(v);
        }
    }

    constexpr int inf = 1E9;

    std::vector<int> mn(n, inf);
    {
        std::queue<int> q;
        std::vector<bool> inq(n, false);
        mn[0] = a[0];
        q.push(0);
        inq[0] = true;

        while (!q.empty()) {
            int u = q.front();
            q.pop();
            inq[u] = false;

            for (int v : g[u]) {
                if (mn[v] > std::min(mn[u], a[v])) {
                    mn[v] = std::min(mn[u], a[v]);
                    if (!inq[v]) {
                        inq[v] = true;
                        q.push(v);
                    }
                }
            }
        }
    }

    std::vector<int> mx(n, -inf);
    {
        std::queue<int> q;
        std::vector<bool> inq(n, false);
        mx[n - 1] = a[n - 1];
        q.push(n - 1);
        inq[n - 1] = true;

        while (!q.empty()) {
            int u = q.front();
            q.pop();
            inq[u] = false;

            for (int v : rg[u]) {
                if (mx[v] < std::max(mx[u], a[v])) {
                    mx[v] = std::max(mx[u], a[v]);
                    if (!inq[v]) {
                        inq[v] = true;
                        q.push(v);
                    }
                }
            }
        }
    }

    int ans = 0;
    for (int i = 0; i < n; ++i) {
        if (mn[i] == inf || mx[i] == -inf) {
            continue;
        }
        ans = std::max(ans, mx[i] - mn[i]);
    }

    std::cout << ans << '\n';
    return 0;
}

XOR 问题

数组A全部xor 一个数,使得最大值最小
问题

Trie

#include <bits/stdc++.h>

using i64 = long long;

constexpr int N = 1E7;

int tot;
int trie[N][2];

int newNode() {
    ++tot;
    trie[tot][0] = trie[tot][1] = 0;
    return tot;
}

void insert(int x) {
    int p = 1;
    for (int i = 30; i >= 0; --i) {
        int u = x >> i & 1;
        if (!trie[p][u]) {
            trie[p][u] = newNode();
        }
        p = trie[p][u];
    }
}


int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);

    int n;
    std::cin >> n;

    std::vector<int> a(n);
    for (int i = 0; i < n; ++i) {
        std::cin >> a[i];
    }

    tot = 0;
    newNode();

    for (int x : a) {
        insert(x);
    }

    auto dfs = [&](this auto &&self, int p, int k) -> int {
        if (p == 0) {
            return 0;
        }
        if (trie[p][0] && trie[p][1]) {
            return std::min(self(trie[p][0], k - 1), self(trie[p][1], k - 1)) | 1 << k;
        }
        return self(std::max(trie[p][0], trie[p][1]), k - 1);
    };
    
    std::cout << dfs(1, 30);
}

sort + partition_point

#include <bits/stdc++.h>

using i64 = long long;

int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    
    int N;
    std::cin >> N;
    
    std::vector<int> a(N);
    for (int i = 0; i < N; i++) {
        std::cin >> a[i];
    }
    
    std::sort(a.begin(), a.end());
    
    auto solve = [&](auto solve, int l, int r, int k) {
        if (k == 0) return 0;
        int m = std::partition_point(a.begin() + l, a.begin() + r, [&](int x) { return ~x >> (k - 1) & 1; }) - a.begin();
        if (l == m || m == r) return solve(solve, l, r, k - 1);
        return std::min(solve(solve, l, m, k - 1), solve(solve, m, r, k - 1)) | 1 << (k - 1);
    };
    
    std::cout << solve(solve, 0, N, 30) << "\n";
    
    return 0;
}

数组中 $ A_i + A_j = C$ 的个数

题目

二分

#include <bits/stdc++.h>

using i64 = long long;

int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);

    int n, c;
    std::cin >> n >> c;

    std::vector<int> a(n);
    for (int i = 0; i < n; ++i) {
        std::cin >> a[i];
    }

    std::sort(a.begin(), a.end());

    i64 ans = 0;
    for (int i = 0; i < n; ++i) {
        int x = a[i] - c;
        ans += std::upper_bound(a.begin(), a.end(), x) - std::lower_bound(a.begin(), a.end(), x);
    }

    std::cout << ans << "\n";
}

双指针

#include <bits/stdc++.h>

using i64 = long long;

int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);

    int n, c;
    std::cin >> n >> c;

    std::vector<int> a(n);
    for (int i = 0; i < n; ++i) {
        std::cin >> a[i];
    }

    std::sort(a.begin(), a.end());

    i64 ans = 0;
    for (int i = 0, l = 0, r = 0; i < n; ++i) {
        int x = a[i] - c;
        while (a[l] < x) {
            ++l;
        }
        while (a[r] <= x) {
            ++r;
        }
        ans += r - l;
    }

    std::cout << ans << "\n";
}

hash表

#include <bits/stdc++.h>

using i64 = long long;

int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);

    i64 n, c;
    std::cin >> n >> c;

    std::vector<i64> v(n);
    for (int i = 0; i < n; ++i) {
        std::cin >> v[i];
    }

    std::unordered_map<i64, int> h;
    i64 re = 0;
    for (i64 x : v) {
        re += h[x - c] + h[c + x];
        ++h[x];
    }
    std::cout << re;

    return 0;   // 结束了罪恶的一生!
}   

仓库选址

104. 货仓选址

数轴上n个人的坐标,问走的一起的总路程最小是多少?

#include <bits/stdc++.h>

using i64 = long long;

int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    
    int n;
    std::cin >> n;

    std::vector<int> a(n);
    for (int i = 0; i < n; ++i) {
        std::cin >> a[i];
    }

    int m = n / 2;
    std::sort(a.begin(), a.end());
    
    i64 ans = 0;
    for (int x : a) {
        ans += std::abs(x - a[m]);
    }
    std::cout << ans << "\n";
}
#include <bits/stdc++.h>

using i64 = long long;

int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    
    int n;
    std::cin >> n;

    std::vector<int> a(n);
    for (int i = 0; i < n; ++i) {
        std::cin >> a[i];
    }

    std::sort(a.begin(), a.end());
    
    i64 ans = 0;
    for (int i = 0; i < n; ++i) {
        ans += a[i] - a[i / 2];
    }
    std::cout << ans << "\n";
}
#include <bits/stdc++.h>

using i64 = long long;

int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    
    int n;
    std::cin >> n;

    std::vector<int> a(n);
    for (int i = 0; i < n; ++i) {
        std::cin >> a[i];
    }

    int m = n / 2;
    std::nth_element(a.begin(), a.begin() + m, a.end());
    
    i64 ans = 0;
    for (int x : a) {
        ans += std::abs(x - a[m]);
    }
    std::cout << ans << "\n";
}
#include <bits/stdc++.h>

using i64 = long long;

int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    
    int n;
    std::cin >> n;

    constexpr int N = 4E4 + 5;
    std::vector<int> cnt(N);
    for (int i = 0, x; i < n; ++i) {
        std::cin >> x;
        ++cnt[x];
    }

    i64 ans = 0;
    for (int i = 0, s = 0; i < N; ++i) {
        s += cnt[i];
        ans += std::min(s, n - s);
    }
    std::cout << ans << "\n";
}

倍增可以 按位和二分查询

题目
l区间and >= k 的最右侧 r

#include <bits/stdc++.h>

using i64 = long long;

void solve() {
    int n;
    std::cin >> n;

    std::vector<int> a(n);
    for (int i = 0; i < n; ++i) {
        std::cin >> a[i];
    }

    int L = std::__lg(n);
    std::vector val(L + 1, std::vector<int>(n));
    
    val[0] = a;
    for (int i = 0; i < L; ++i) {
        for (int j = 0; j + (1 << i) < n; ++j) {
            val[i + 1][j] = val[i][j] & val[i][j + (1 << i)];
        }
    }

    auto qry = [&](int l, int r) -> int {
        int len = std::__lg(r - l);
        return val[len][l] & val[len][r - (1 << len)];
    };

    int q;
    std::cin >> q;

    for (int i = 0; i < q; ++i) {
        int l, k;
        std::cin >> l >> k;
        --l;
        
        int lo = l, hi = n;
        while (lo < hi) {
            auto mid = lo + (hi - lo + 1) / 2;
            if (qry(l, mid) >= k) {
                lo = mid;
            } else {
                hi = mid - 1;
            }
        }
        std::cout << (lo == l ? -1 : lo) << " ";

        // int x = (1 << 30) - 1;
        // int p = l;
        // for (int j = L; j >= 0 && p < n; --j) {
        //     if ((val[j][p] & x) >= k) {
        //         x &= val[j][p];
        //         p += 1 << j;
        //     }
        // }
        // std::cout << (p == l ? -1 : p) << " ";
    }
    std::cout << std::endl;
}

int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);

    int t;
    std::cin >> t;

    while (t--) {
        solve();
    }
}

二分图判断 DSU

博客有一场CF E题
Codeforces Round 805 (Div. 3)

posted @ 2026-03-13 15:29  filt  阅读(6)  评论(0)    收藏  举报