Submission #1125655

#TimeUsernameProblemLanguageResultExecution timeMemory
1125655ShadowSharkRigged Roads (NOI19_riggedroads)C++20
100 / 100
298 ms85896 KiB
#include <bits/stdc++.h>
using namespace std;

const int maxN = 3e5 + 5;
vector<pair<int, int>> adj[maxN];
pair<int, int> edge[maxN];
int par[maxN], belong[maxN], ans[maxN], ask[maxN];
int depth[maxN], pos[maxN], RMQ[21][2 * maxN], tick = 0;

void dfs(int u, int pre) {
    RMQ[0][++tick] = u; pos[u] = tick;
    for (auto it: adj[u]) {
        int v = it.first, id = it.second;
        if (v == pre) continue;

        belong[v] = id;
        par[v] = u;
        depth[v] = depth[u] + 1;

        dfs(v, u);
        RMQ[0][++tick] = u;
    }
}

/// DSU
int pre[maxN], sz[maxN], Top[maxN];

int find_set(int u) {
    return (u == pre[u]) ? u : pre[u] = find_set(pre[u]);
}

void union_set(int u, int v) {
    u = find_set(u);
    v = find_set(v);

    if (u == v) return ;

    if (sz[u] < sz[v]) swap(u, v);
    pre[v] = u;
    sz[u] += sz[v];
    if (depth[Top[u]] > depth[Top[v]]) Top[u] = Top[v];
}

int min_depth(int x, int y) {return (depth[x] < depth[y]) ? x : y;};

int getLCA(int u, int v) {
	int l = pos[u], r = pos[v];
	if (l > r) swap(l, r);

	int k = 31 - __builtin_clz(r - l + 1);
	return min_depth(RMQ[k][l], RMQ[k][r - (1 << k) + 1]);
}

int main() {
    ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);

    int n, m;
    cin >> n >> m;

    for (int i = 1; i <= m; i++) {
        int u, v;
        cin >> u >> v;

        edge[i] = {u, v};
    }

    for (int i = 1; i < n; i++) {
        int id; cin >> id;
        auto [u, v] = edge[id];
        ask[id] = 1;

        adj[u].push_back({v, id});
        adj[v].push_back({u, id});
    }

    depth[1] = 1;
    dfs(1, 1);

    for (int j = 1; (1 << j) <= tick; j++)
        for (int i = 1; i <= tick - (1 << j) + 1; i++)
            RMQ[j][i] = min_depth(RMQ[j - 1][i], RMQ[j - 1][i + (1 << (j - 1))]);

    for (int i = 1; i <= n; i++) {
        pre[i] = i;
        sz[i] = 1;
        Top[i] = i;
    }

    int curr_idx = 1;
    vector<int> rem, add;
    for (int i = 1; i <= m; i++) {
        if (ans[i]) continue;
        auto [u, v] = edge[i];

        int lca = getLCA(u, v);

        /// All edge not visited
        int tick = 0;
        while (true) {
            u = find_set(u);
            rem.push_back(u);

            if (depth[Top[u]] <= depth[lca]) break;

            add.push_back(belong[Top[u]]);
            u = par[Top[u]];
        }

        while (true) {
            v = find_set(v);
            rem.push_back(v);

            if (depth[Top[v]] <= depth[lca]) break;

            add.push_back(belong[Top[v]]);
            v = par[Top[v]];
        }

        if (add.size()) {
            sort(add.begin(), add.end());
            for (auto x: add)
                ans[x] = curr_idx++;
        }

        for (auto x: rem)
            union_set(x, u);

        rem.clear(); add.clear();

        if (!ask[i]) ans[i] = curr_idx++;
    }

    for (int i = 1; i <= m; i++)
        cout << ans[i] << ' ';
    return 0;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...