Submission #1127631

#TimeUsernameProblemLanguageResultExecution timeMemory
1127631_callmelucianRigged Roads (NOI19_riggedroads)C++17
100 / 100
388 ms42052 KiB
#include <bits/stdc++.h> using namespace std; typedef long long ll; typedef long double ld; typedef pair<ll,ll> pl; typedef pair<int,int> pii; typedef tuple<int,int,int> tpl; #define all(a) a.begin(), a.end() #define filter(a) a.erase(unique(all(a)), a.end()) const int mn = 3e5 + 5; struct BIT { vector<int> tr; BIT (int sz) : tr(sz + 1) {} int p (int k) { return k & -k; } void update (int k, int val) { for (; k < tr.size(); k += p(k)) tr[k] += val; } int preSum (int k, int ans = 0) { for (; k; k -= p(k)) ans += tr[k]; return ans; } int query (int l, int r) { return preSum(r) - preSum(l - 1); } int walk (int targ) { int ans = 0, lg = 31 - __builtin_clz(tr.size()), sum = 0; for (int mask = 1 << lg; mask; mask >>= 1) { if ((ans | mask) < tr.size() && sum + tr[ans | mask] < targ) ans |= mask, sum += tr[ans]; } return ans; } int walkRange (int targ, int from) { int need = targ + preSum(from - 1); return walk(need); } } tree(mn); int num[mn], chain[mn], depth[mn], sz[mn]; int par[mn], idx[mn], place[mn], node[mn]; int checkPoint, timeDfs, n, m; vector<pii> adj[mn]; bool inTree[mn]; pii edge[mn]; vector<int> clearRange (int l, int r) { vector<int> vec; while (int cur = tree.query(l, r)) { int pos = tree.walkRange(cur, l) + 1; vec.push_back(node[pos]); tree.update(pos, -1); } return vec; } int szDfs (int u, int p) { sz[u] = 1; for (pii item : adj[u]) { int v = item.first; if (v != p) sz[u] += szDfs(v, u); } return sz[u]; } void dfs (int u, int p, int d, int upID, bool toP) { if (u == 1) szDfs(u, p); else idx[u] = upID; num[u] = ++timeDfs, depth[u] = d, node[timeDfs] = u; chain[u] = (toP ? chain[p] : u), par[u] = p; sort(all(adj[u]), [&] (pii a, pii b) { return sz[a.first] > sz[b.first]; }); bool heavy = 1; for (pii item : adj[u]) { int v, id; tie(v, id) = item; if (v != p) dfs(v, u, d + 1, id, heavy), heavy = 0; } } void append (vector<int> &source, const vector<int> &app) { source.insert(source.end(), all(app)); } void process (int a, int b) { vector<int> vec; while (chain[a] != chain[b]) { int ap = par[chain[a]], bp = par[chain[b]]; if (depth[ap] == depth[bp]) { append(vec, clearRange(num[chain[a]], num[a])), a = ap; append(vec, clearRange(num[chain[b]], num[b])), b = bp; } else if (depth[ap] > depth[bp]) append(vec, clearRange(num[chain[a]], num[a])), a = ap; else if (depth[bp] > depth[ap]) append(vec, clearRange(num[chain[b]], num[b])), b = bp; } if (depth[a] > depth[b]) swap(a, b); if (num[a] + 1 <= num[b]) append(vec, clearRange(num[a] + 1, num[b])); sort(all(vec), [&] (int a, int b) { return idx[a] < idx[b]; }); for (int u : vec) place[idx[u]] = ++checkPoint; } int main() { ios::sync_with_stdio(0); cin.tie(0); cin >> n >> m; for (int i = 1; i <= m; i++) { int a, b; cin >> a >> b; edge[i] = {a, b}; } for (int i = 1; i < n; i++) { int id, a, b; cin >> id; inTree[id] = 1, tie(a, b) = edge[id]; adj[a].emplace_back(b, id); adj[b].emplace_back(a, id); } dfs(1, 0, 1, -1, 0); for (int i = 2; i <= n; i++) tree.update(num[i], 1); for (int i = 1; i <= m; i++) { int a, b; tie(a, b) = edge[i]; if (depth[a] < depth[b]) swap(a, b); if (inTree[i]) { if (!place[i]) place[i] = ++checkPoint, tree.update(num[a], -1); cout << place[i] << " "; } else { process(a, b); cout << ++checkPoint << " "; } } 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...