#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 time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |