#include<bits/stdc++.h>
#define int long long
#define ii pair<int,int>
using namespace std;
const int maxn = 3e5 + 5;
int n, m;
int head[maxn], id[maxn], ind[maxn], sz[maxn], par[maxn], h[maxn], ans[maxn], mark[maxn], who[maxn], chosen[maxn];
vector<ii> adj[maxn];
array<int, 2> edges[maxn];
vector<int> order;
struct DS{
    int seg[4 * maxn];
    void upd(int pos, int val, int id = 1, int l = 1, int r = m)
    {
        if (l == r) return seg[id] = val, void();
        int mid = (l + r) / 2;
        if (pos <= mid) upd(pos, val, id * 2, l, mid);
        else upd(pos, val, id * 2 + 1, mid + 1, r);
        seg[id] = seg[id * 2] + seg[id * 2 + 1];
    }
    int qry(int lx, int rx, int id = 1, int l = 1, int r = m)
    {
        if (lx > r || l > rx || lx > rx) return 0;
        if (lx <= l && r <= rx) return seg[id];
        int mid = (l + r) / 2;
        return qry(lx, rx, id * 2, l, mid) + qry(lx, rx, id * 2 + 1, mid + 1, r);
    }
    int walk(int k = 1, int id = 1, int l = 1, int r = m)
    {
        if (l == r) return l;
        int mid = (l + r) / 2;
        int nothing = mid - l + 1 - seg[id * 2];
        if (nothing >= k) return walk(k, id * 2, l, mid);
        return walk(k - nothing, id * 2 + 1, mid + 1, r);
    }
    int get(int lx, int rx, int id = 1, int l = 1, int r = m)
    {
        if (l > rx || lx > r) return -1;
        if (l == r) return l;
        int mid = (l + r) / 2;
        int ans = -1;
        if (seg[id * 2] != mid - l + 1) ans = get(lx, rx, id * 2, l, mid);
        if (ans != -1) return ans;
        if (seg[id * 2 + 1] != r - mid) return get(lx, rx, id * 2 + 1, mid + 1, r);
        return -1;
    }
} IND, HLD;
void dfs(int x = 1, int p = 0)
{
    sz[x] = 1;
    for (auto i : adj[x]) if (i.first != p)
        dfs(i.first, x),
        sz[x] += sz[i.first];
}
void hld(pair<int,int> pa = {1, 0}, int p = 0, int top = 1)
{
    static int cnt = 0;
    int x = pa.first;
    head[x] = top;
    par[x] = p;
    h[x] = h[p] + 1;
    id[x] = ++cnt;
    who[cnt] = x;
    ind[cnt] = pa.second;
    ii fat = {-1, -1};
    for (auto i : adj[x]) if (i.first != p)
        fat = max(fat, make_pair(sz[i.first], i.first));
    if (fat.second != -1)
        for (auto i : adj[x]) if (i.first != p && i.first == fat.second)
            hld(i, x, top);
    for (auto i : adj[x]) if (i.first != p && i.first != fat.second)
        hld(i, x, i.first);
}
int qry(int u, int v)
{
    vector<int> path;
    while (head[u] != head[v])
    {
        if (h[head[u]] > h[head[v]]) swap(u, v);
        while (true)
        {
            int x = HLD.get(id[head[v]], id[v]);
            if (x == -1) break;
            path.emplace_back(who[x]);
            int rem = IND.walk();
            IND.upd(rem, 1);
            HLD.upd(x, 1);
        }
        v = par[head[v]];
    }
    if (id[u] > id[v]) swap(u, v);
    while (true)
    {
        int x = HLD.get(id[u] + 1, id[v]);
        if (x == -1) break;
        path.emplace_back(who[x]);
        int rem = IND.walk();
        IND.upd(rem, 1);
        HLD.upd(x, 1);
    }
    sort(path.begin(), path.end(), [](int x, int y){
            x = id[x];
            y = id[y];
            return ind[x] < ind[y];
         });
    for (int i : path)
        order.emplace_back(i);
    return path.size();
}
signed main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
//    freopen("test.inp", "r", stdin);
//    freopen("test.out", "w", stdout);
    cin >> n >> m;
    for (int i = 1; i <= m; i++)
        cin >> edges[i][0] >> edges[i][1];
    for (int j = 1, i; j < n; j++)
        cin >> i,
        chosen[i] = 1,
        adj[edges[i][0]].emplace_back(edges[i][1], i),
        adj[edges[i][1]].emplace_back(edges[i][0], i);
    dfs();
    hld();
    for (int i = 1; i <= m; i++)
    {
        int u = edges[i][0], v = edges[i][1];
        if (h[u] > h[v]) swap(u, v);
        if (chosen[i])
        {
            if (!HLD.qry(id[v], id[v]))
            {
                ans[i] = IND.walk();
                IND.upd(ans[i], 1);
                mark[ans[i]] = 1;
                HLD.upd(id[v], 1);
            }
            continue;
        }
        int blank = qry(edges[i][0], edges[i][1]);
        ans[i] = IND.walk();
        IND.upd(ans[i], 1);
        mark[ans[i]] = 1;
    }
    int cur = 1;
    for (int i : order)
    {
        i = ind[id[i]];
        if (ans[i]) continue;
        while (mark[cur]) cur++;
        ans[i] = cur;
        mark[cur] = 1;
    }
    for (int i = 1; i <= m; i++)
    {
        if (ans[i]) continue;
        while (mark[cur]) cur++;
        ans[i] = cur;
        mark[cur] = 1;
    }
    for (int i = 1; i <= m; i++)
        cout << ans[i] << " ";
}
| # | 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... |