This submission is migrated from previous version of oj.uz, which used different machine for grading. This submission may have different result if resubmitted.
#ifndef LOCAL
#define FAST_IO
#endif
// ============
#include <algorithm>
#include <array>
#include <bitset>
#include <cassert>
#include <cmath>
#include <iomanip>
#include <iostream>
#include <list>
#include <map>
#include <numeric>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <string>
#include <tuple>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>
#define OVERRIDE(a, b, c, d, ...) d
#define REP2(i, n) for (i32 i = 0; i < (i32) (n); ++i)
#define REP3(i, m, n) for (i32 i = (i32) (m); i < (i32) (n); ++i)
#define REP(...) OVERRIDE(__VA_ARGS__, REP3, REP2)(__VA_ARGS__)
#define PER(i, n) for (i32 i = (i32) (n) - 1; i >= 0; --i)
#define ALL(x) begin(x), end(x)
using namespace std;
using u32 = unsigned int;
using u64 = unsigned long long;
using u128 = __uint128_t;
using i32 = signed int;
using i64 = signed long long;
using i128 = __int128_t;
using f64 = double;
using f80 = long double;
template <typename T>
using Vec = vector<T>;
template <typename T>
bool chmin(T &x, const T &y) {
if (x > y) {
x = y;
return true;
}
return false;
}
template <typename T>
bool chmax(T &x, const T &y) {
if (x < y) {
x = y;
return true;
}
return false;
}
istream &operator>>(istream &is, i128 &x) {
i64 v;
is >> v;
x = v;
return is;
}
ostream &operator<<(ostream &os, i128 x) {
os << (i64) x;
return os;
}
istream &operator>>(istream &is, u128 &x) {
u64 v;
is >> v;
x = v;
return is;
}
ostream &operator<<(ostream &os, u128 x) {
os << (u64) x;
return os;
}
[[maybe_unused]] constexpr i32 INF = 1000000100;
[[maybe_unused]] constexpr i64 INF64 = 3000000000000000100;
struct SetUpIO {
SetUpIO() {
#ifdef FAST_IO
ios::sync_with_stdio(false);
cin.tie(nullptr);
#endif
cout << fixed << setprecision(15);
}
} set_up_io;
// ============
#ifdef DEBUGF
#else
#define DBG(x) (void) 0
#endif
// ============
#include <algorithm>
#include <cassert>
#include <utility>
#include <vector>
class HeavyLightDecomposition {
std::vector<int> siz;
std::vector<int> par;
std::vector<int> hea;
std::vector<int> in;
std::vector<int> out;
std::vector<int> dep;
std::vector<int> rev;
template <typename G>
void dfs1(G &g, int v) {
if (!g[v].empty() && (int) g[v][0] == par[v]) {
std::swap(g[v][0], g[v].back());
}
for (auto &e : g[v]) {
int u = (int)e;
if (u != par[v]) {
par[u] = v;
dfs1(g, u);
siz[v] += siz[u];
if (siz[u] > siz[(int) g[v][0]]) {
std::swap(g[v][0], e);
}
}
}
}
template <typename G>
void dfs2(const G &g, int v, int &time) {
in[v] = time;
rev[time++] = v;
for (auto &e : g[v]) {
int u = (int)e;
if (u == par[v]) {
continue;
}
if (u == (int) g[v][0]) {
hea[u] = hea[v];
} else {
hea[u] = u;
}
dep[u] = dep[v] + 1;
dfs2(g, u, time);
}
out[v] = time;
}
public:
template <typename G>
HeavyLightDecomposition(G &g, int root = 0) :
siz(g.size(), 1),
par(g.size(), root),
hea(g.size(), root),
in(g.size(), 0),
out(g.size(), 0),
dep(g.size(), 0),
rev(g.size(), 0) {
assert(root >= 0 && root < (int) g.size());
dfs1(g, root);
int time = 0;
dfs2(g, root, time);
}
int subtree_size(int v) const {
assert(v >= 0 && v < (int) siz.size());
return siz[v];
}
int parent(int v) const {
assert(v >= 0 && v < (int) par.size());
return par[v];
}
int in_time(int v) const {
assert(v >= 0 && v < (int) in.size());
return in[v];
}
int out_time(int v) const {
assert(v >= 0 && v < (int) out.size());
return out[v];
}
int depth(int v) const {
assert(v >= 0 && v < (int) dep.size());
return dep[v];
}
int time_to_vertex(int t) const {
assert(t >= 0 && t < (int) rev.size());
return rev[t];
}
int la(int v, int k) const {
assert(v >= 0 && v < (int) dep.size());
assert(k >= 0);
if (k > dep[v]) {
return -1;
}
while (true) {
int u = hea[v];
if (in[u] + k <= in[v]) {
return rev[in[v] - k];
}
k -= in[v] - in[u] + 1;
v = par[u];
}
return 0;
}
int forward(int v, int dst) const {
assert(v >= 0 && v < (int) dep.size());
assert(dst >= 0 && dst < (int) dep.size());
assert(v != dst);
int l = lca(v, dst);
if (l == v) {
return la(dst, dist(v, dst) - 1);
} else {
return par[v];
}
}
int lca(int u, int v) const {
assert(u >= 0 && u < (int) dep.size());
assert(v >= 0 && v < (int) dep.size());
while (u != v) {
if (in[u] > in[v]) {
std::swap(u, v);
}
if (hea[u] == hea[v]) {
v = u;
} else {
v = par[hea[v]];
}
}
return u;
}
int dist(int u, int v) const {
assert(u >= 0 && u < (int) dep.size());
assert(v >= 0 && v < (int) dep.size());
return dep[u] + dep[v] - 2 * dep[lca(u, v)];
}
std::vector<std::pair<int, int>> path(int u, int v, bool edge) const {
assert(u >= 0 && u < (int) dep.size());
assert(v >= 0 && v < (int) dep.size());
std::vector<std::pair<int, int>> fromu, fromv;
bool rev = false;
while (true) {
if (u == v && edge) {
break;
}
if (in[u] > in[v]) {
std::swap(u, v);
std::swap(fromu, fromv);
rev ^= true;
}
if (hea[u] == hea[v]) {
fromv.emplace_back(in[v], in[u] + (int)edge);
v = u;
break;
} else {
fromv.emplace_back(in[v], in[hea[v]]);
v = par[hea[v]];
}
}
if (rev) {
std::swap(fromu, fromv);
}
std::reverse(fromv.begin(), fromv.end());
fromu.reserve(fromv.size());
for (auto [x, y] : fromv) {
fromu.emplace_back(y, x);
}
return fromu;
}
int jump(int u, int v, int k) const {
assert(u >= 0 && u < (int) dep.size());
assert(v >= 0 && v < (int) dep.size());
assert(k >= 0);
int l = lca(u, v);
int dis = dep[u] + dep[v] - 2 * dep[l];
if (k > dis) {
return -1;
}
if (k <= dep[u] - dep[l]) {
return la(u, k);
} else {
return la(v, dis - k);
}
}
int meet(int u, int v, int w) const {
return lca(u, v) ^ lca(v, w) ^ lca(w, u);
}
};
// ============
// ============
#include <cassert>
#include <utility>
#include <vector>
template <typename MonoidFunc>
class LazySegmentTree {
public:
using Value = typename MonoidFunc::Value;
using Func = typename MonoidFunc::Func;
private:
int old_length;
int lg;
int length;
std::vector<Value> values;
std::vector<Func> funcs;
static int lg2(int n) {
int x = 1;
int l = 0;
while (x < n) {
x <<= 1;
++l;
}
return l;
}
void _apply(int idx, const Func &func) {
values[idx] = MonoidFunc::apply(func, values[idx]);
funcs[idx] = MonoidFunc::composite(func, funcs[idx]);
}
void push(int idx) {
_apply(idx << 1, funcs[idx]);
_apply(idx << 1 | 1, funcs[idx]);
funcs[idx] = MonoidFunc::func_id();
}
void recalc_values(int idx) {
values[idx] = MonoidFunc::op(values[idx << 1], values[idx << 1 | 1]);
}
public:
LazySegmentTree(int n) :
old_length(n),
lg(lg2(n)),
length(1 << lg),
values(length << 1, MonoidFunc::id()),
funcs(length << 1, MonoidFunc::func_id()) {
assert(n >= 0);
}
LazySegmentTree(const std::vector<Value> &v) :
old_length((int) v.size()),
lg(lg2(old_length)),
length(1 << lg),
values(length << 1, MonoidFunc::id()),
funcs(length << 1, MonoidFunc::func_id()) {
for (int i = 0; i < old_length; ++i) {
values[i + length] = v[i];
}
for (int i = length - 1; i > 0; --i) {
recalc_values(i);
}
}
template <typename F>
LazySegmentTree(int n, const F &f) :
old_length(n),
lg(lg2(n)),
length(1 << lg),
values(length << 1, MonoidFunc::id()),
funcs(length << 1, MonoidFunc::func_id()) {
for (int i = 0; i < old_length; ++i) {
values[i + length] = f(i);
}
for (int i = length - 1; i > 0; --i) {
recalc_values(i);
}
}
void update(int idx, Value val) {
assert(idx >= 0 && idx < old_length);
idx += length;
for (int i = lg; i > 0; --i) {
push(idx >> i);
}
values[idx] = std::move(val);
while (idx >>= 1) {
recalc_values(idx);
}
}
void apply(int l, int r, const Func &func) {
assert(l >= 0 && l <= r && r <= old_length);
if (l == r) {
return;
}
l += length;
r += length;
int _l = l;
int _r = r;
for (int i = lg; i > 0; --i) {
push(_l >> i);
push((_r - 1) >> i);
}
while (l < r) {
if (l & 1) {
_apply(l++, func);
}
if (r & 1) {
_apply(--r, func);
}
l >>= 1;
r >>= 1;
}
for (int i = 1; i <= lg; ++i) {
if ((_l >> i << i) != _l) {
recalc_values(_l >> i);
}
if ((_r >> i << i) != _r) {
recalc_values((_r - 1) >> i);
}
}
}
Value prod(int l, int r) {
assert(l >= 0 && l <= r && r <= old_length);
if (l == r) {
return MonoidFunc::id();
}
l += length;
r += length;
for (int i = lg; i > 0; --i) {
push(l >> i);
push((r - 1) >> i);
}
Value lp = MonoidFunc::id();
Value rp = MonoidFunc::id();
while (l < r) {
if (l & 1) {
lp = MonoidFunc::op(lp, values[l++]);
}
if (r & 1) {
rp = MonoidFunc::op(values[--r], rp);
}
l >>= 1;
r >>= 1;
}
return MonoidFunc::op(lp, rp);
}
Value all_prod() const {
return values[1];
}
};
// ============
struct Upd1 {
using Value = pair<i32, i32>;
using Func = bool;
static Value id() {
return Value(0, 0);
}
static Value op(const Value &x, const Value &y) {
return Value(x.first + y.first, x.second + y.second);
}
static Func func_id() {
return false;
}
static Func composite(Func f, Func g) {
return f || g;
}
static Value apply(Func f, const Value &x) {
if (f) {
return Value(x.second, x.second);
} else {
return x;
}
}
};
class RangeChmin {
i32 n;
Vec<i32> data;
public:
RangeChmin(i32 n) : n(n), data(2 * n, INF) {}
void range_chmin(i32 l, i32 r, i32 v) {
l += n;
r += n;
while (l < r) {
if (l % 2 == 1) {
chmin(data[l++], v);
}
if (r % 2 == 1) {
chmin(data[--r], v);
}
l /= 2;
r /= 2;
}
}
i32 at(i32 idx) const {
i32 ret = INF;
idx += n;
while (idx > 0) {
chmin(ret, data[idx]);
idx /= 2;
}
return ret;
}
};
int main() {
i32 n, m;
cin >> n >> m;
Vec<pair<i32, i32>> edges(m);
for (auto &[u, v] : edges) {
cin >> u >> v;
--u;
--v;
}
Vec<i32> r(n - 1);
REP(i, n - 1) {
cin >> r[i];
--r[i];
}
Vec<i32> is_in(m, 0);
for (i32 ei : r) {
is_in[ei] = 1;
}
Vec<Vec<i32>> tree(n);
for (i32 ei : r) {
auto [u, v] = edges[ei];
tree[u].emplace_back(v);
tree[v].emplace_back(u);
}
HeavyLightDecomposition hld(tree);
LazySegmentTree<Upd1> seg(n, [&](i32) -> Upd1::Value {
return Upd1::Value(0, 1);
});
RangeChmin rc(n);
i32 nxt = 0;
Vec<i32> ans(m, -1);
Vec<i32> used(m, 0);
REP(i, m) {
if (is_in[i]) {
auto &[u, v] = edges[i];
if (hld.depth(u) > hld.depth(v)) {
swap(u, v);
}
if (rc.at(hld.in_time(v)) != INF) {
continue;
}
seg.apply(hld.in_time(v), hld.in_time(v) + 1, true);
ans[i] = nxt;
used[nxt++] = 1;
} else {
auto [u, v] = edges[i];
Upd1::Value path = Upd1::id();
for (auto [l, r] : hld.path(u, v, true)) {
if (l > r) {
swap(l, r);
}
path = Upd1::op(path, seg.prod(l, r + 1));
}
nxt += path.second - path.first;
for (auto [l, r] : hld.path(u, v, true)) {
if (l > r) {
swap(l, r);
}
rc.range_chmin(l, r + 1, nxt);
seg.apply(l, r + 1, true);
}
ans[i] = nxt;
used[nxt++] = 1;
}
}
Vec<i32> pct;
for (i32 ei : r) {
if (ans[ei] == -1) {
pct.push_back(ei);
}
}
sort(ALL(pct), [&](i32 i, i32 j) -> bool {
return make_pair(rc.at(hld.in_time(edges[i].second)), i) < make_pair(rc.at(hld.in_time(edges[j].second)), j);
});
nxt = 0;
for (i32 i : pct) {
while (used[nxt]) {
++nxt;
}
ans[i] = nxt++;
}
REP(i, m) {
cout << ans[i] + 1 << " \n"[i + 1 == m];
}
}
# | 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... |