求调悬关【WA on #7,8】
查看原帖
求调悬关【WA on #7,8】
376970
fishPJ楼主2024/10/4 22:34

rt,tarjan缩点+欧拉序LCA+差分,实在调不出来了

#include<bits/stdc++.h>
#define rep(i, a, b) for(int i = a; i <= b; i++)
#define per(i, a, b) for(int i = a; i >= b; i--)
#define int long long
#define RD read()
using namespace std;
inline int read() {
    int x = 0, f = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9') { if(ch == '-') f = -1; ch = getchar(); }
    while('0' <= ch && ch <= '9') { x = (x << 1) + (x << 3) + (ch ^ 48); ch = getchar(); }
    return x * f;
}
int const N = 5e5 + 5, M = 2e6 + 5;
int n, m, q;
// vector<int> G[N], g[N];
int h[N], to[M << 1], nxt[M << 1], cnt = 1;
void add(int u, int v) {
    to[++cnt] = v;
    nxt[cnt] = h[u];
    h[u] = cnt;
}
int hh[N], tto[M << 1], nnxt[M << 1], ccnt = 1;
void Add(int u, int v) {
    tto[++ccnt] = v;
    nnxt[ccnt] = hh[u];
    hh[u] = ccnt;
}
int tot, idx, id[N], dfn[N], low[N], sum[N], a[N];
bool instk[N];
stack<int> stk;
bool vis[N];
void tarjan(int u, int pre) {
    low[u] = dfn[u] = ++idx;
    instk[u] = 1, stk.push(u);
    for(int e = h[u], v; e; e = nxt[e]) if((v = to[e]) != pre) {
        if(!dfn[v]) {
            tarjan(v, u);
            low[u] = min(low[u], low[v]);
        } else if(instk[v]) {
            low[u] = min(low[u], dfn[v]);
        }
    }
    if(low[u] == dfn[u]) {
        tot ++;
        while(1) {
            int t = stk.top(); stk.pop();
            instk[t] = 0;
            sum[tot] += a[t];
            id[t] = tot;
            if(t == u) break;
        }
    }
}
int f[N << 1][21], dep[N], c[N], num, ind[N], fa[N];
void dfs(int u, int pre) {
    fa[u] = pre;
    f[++ num][0] = u, ind[u] = num;
    dep[u] = dep[pre] + 1;
    for(int e = hh[u], v; e; e = nnxt[e]) if((v = tto[e]) != pre) {
        dfs(v, u), f[++ num][0] = u;
    }
}
int lg[N << 1];
bool comp(int x, int y) { return dep[x] < dep[y] ? x : y; }
void init() {
    dfs(1, 0);
    lg[0] = -1;
    rep(i, 1, num) lg[i] = lg[i >> 1] + 1;
    for(int j = 1; (1ll << j) <= num; j ++) {
        for(int i = 1; i + (1ll << j) - 1 <= num; i ++) {
            f[i][j] = comp(f[i][j - 1], f[i + (1ll << j - 1)][j - 1]);
        }
    }
}
int LCA(int x, int y) {
    x = ind[x], y = ind[y];
    if(x > y) swap(x, y);
    int k = lg[y - x + 1];
    return comp(f[x][k], f[y - (1ll << k) + 1][k]);
}
int ans;
void getAns(int u, int pre) {
    // printf("u = %lld\n", u);
    vis[u] = 1;
    for(int e = hh[u], v; e; e = nnxt[e]) if((v = tto[e]) != pre && !vis[v]) {
        // printf("  v = %lld\n", v);
        getAns(v, u);
        c[u] += c[v];
    }
    if(c[u] > 0) ans += sum[u];
}
#define pii pair<int, int>
pii E[M << 1];
int Cnt;
signed main() {
    n = RD, m = RD;
    rep(i, 1, n) a[i] = RD;
    rep(i, 1, m) {
        int u = RD, v = RD;
        add(u, v), add(v, u);
    }
    rep(i, 1, n) if(!dfn[i]) tarjan(i, 0);
    rep(u, 1, n) {
        for(int e = h[u]; e; e = nxt[e]) {
            int v = to[e]; if(id[u] == id[v]) continue;
            int x = min(id[u], id[v]), y = max(id[u], id[v]);
            E[++ Cnt] = {x, y};
        }
    }
    sort(E + 1, E + 1 + Cnt);
    rep(i, 1, Cnt) {
        if(E[i] == E[i - 1]) continue;
        int u = E[i].first, v = E[i].second;
        Add(u, v), Add(v, u);
    }
    init();
    q = RD;
    while(q --) {
        int x = id[RD], y = id[RD];
        int lca = LCA(x, y);
        // printf("x = %lld, y = %lld, lca = %lld\n", x, y, lca);
        c[x] ++, c[y] ++, c[lca]--, c[fa[lca]]--;
    }
    memset(vis, 0, sizeof vis);
    getAns(1, 0);
    printf("%lld\n", ans);
    return 0;
}
2024/10/4 22:34
加载中...