#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
const int N = 1e5 + 50;
struct segtree {
vector<long long> lazy, sum;
int size = 1;
void init(int n) {
while (size < n) {
size *= 2;
}
lazy.assign(2 * size - 1, 0ll);
sum.assign(2 * size - 1, 0ll);
}
void prop(int x, int lx, int rx) {
if (rx - lx == 1) {
lazy[x] = 0;
return;
}
lazy[2 * x + 1] += lazy[x];
lazy[2 * x + 2] += lazy[x];
sum[2 * x + 1] += lazy[x] * static_cast<long long>(rx - lx) / 2;
sum[2 * x + 2] += lazy[x] * static_cast<long long>(rx - lx) / 2;
lazy[x] = 0;
}
void add(int l, int r, ll v, int x, int lx, int rx) {
if (lx >= l && rx <= r) {
lazy[x] += v;
sum[x] += v * static_cast<long long>(rx - lx);
return;
}
if (rx <= l || lx >= r) {
return;
}
int m = (rx + lx) / 2;
add(l, r, v, 2 * x + 1, lx, m);
add(l, r, v, 2 * x + 2, m, rx);
sum[x] = sum[2 * x + 1] + sum[2 * x + 2] + lazy[x] * (rx - lx);
}
void add(int l, int r, ll val) {
add(l, r, val, 0, 0, size);
}
ll query(ll l, ll r, int x, ll lx, ll rx) {
prop(x, lx, rx);
if (lx >= l && rx <= r) {
return sum[x];
}
if (rx <= l || lx >= r) {
return 0ll;
}
int m = (rx + lx) / 2;
ll s1 = query(l, r, 2 * x + 1, lx, m);
ll s2 = query(l, r, 2 * x + 2, m, rx);
return s1 + s2 + lazy[x] * (rx - lx);
}
ll query(ll l, ll r) {
return query(l, r, 0, 0, size);
}
} tree1, tree2;
int last[N], ans[N], par[N], root[N], depth[N], sz[N], pos[N], rpos[N], ti = 0;
vector<int> G[N];
void dfsSz(int s, int p) {
sz[s] = 1;
depth[s] = depth[p] + 1;
par[s] = p;
if (root[s] == -1) root[s] = s;
for (auto& u : G[s]) {
if (u == p) continue;
dfsSz(u, s);
sz[s] += sz[u];
if (sz[u] > sz[G[s][0]]) swap(G[s][0], u);
}
}
void dfsHld(int s, int p) {
pos[s] = ++ti;
rpos[ti] = s;
for (auto u : G[s]) {
if (u == p) continue;
root[u] = (u == G[s][0] ? root[s] : u);
dfsHld(u, s);
}
}
int highest_ancesor(int u) {
if (tree1.query(pos[root[u]], pos[u] + 1) == pos[u] - pos[root[u]]) {
return root[u];
}
int l = pos[root[u]] - 1, r = pos[u];
while(r - l > 1) {
int mid = (r + l + 1) / 2;
if (tree1.query(mid, pos[u] + 1) != pos[u] - mid) {
l = mid;
} else {
r = mid;
}
}
return rpos[r];
}
void query1(int u) {
int s = u;
int dif = tree2.query(pos[s], pos[s] + 1) - last[s];
while(s != -1) {
int h = highest_ancesor(s);
tree2.add(pos[h], pos[s] + 1 - (s == u), dif);
if (h != root[s] || !h || tree1.query(pos[h], pos[s] + 1) != pos[s] - pos[h] + 1) {
break;
}
s = par[root[s]];
}
}
int query2(int s) {
while(s != -1) {
int h = highest_ancesor(s);
if (h != root[s] || !h || tree1.query(pos[h], pos[s] + 1) != pos[s] - pos[h] + 1) {
return h;
}
s = par[root[s]];
}
return 0;
}
int main()
{
// ifstream cin("input.txt");
// ofstream cout("output.txt");
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
int n, m, q; cin >> n >> m >> q;
vector<array<int, 2>> edges;
for (int i = 0; i < n - 1; i++) {
int u, v; cin >> u >> v;
u--; v--;
G[u].push_back(v);
G[v].push_back(u);
edges.push_back({u, v});
}
dfsSz(0, -1);
dfsHld(0, -1);
tree1.init(n + 1);
tree2.init(n + 1);
for (int i = 0; i < n; i++) {
ans[i] = 1;
last[i] = 0;
tree2.add(pos[i], pos[i] + 1, 1);
}
for (auto& e : edges) {
if (e[0] == par[e[1]]) swap(e[0], e[1]);
}
while(m--) {
int e; cin >> e; e--;
auto [u, v] = edges[e];
if (tree1.query(pos[u], pos[u] + 1) == 0) {
tree1.add(pos[u], pos[u] + 1, 1);
query1(u);
} else {
int anc = query2(u);
last[u] = tree2.query(pos[u], pos[u] + 1);
ll pl = tree2.query(pos[anc], pos[anc] + 1) - last[u];
tree2.add(pos[u], pos[u] + 1, pl);
tree1.add(pos[u], pos[u] + 1, -1);
}
}
while(q--) {
int u; cin >> u; u--;
int anc = query2(u);
cout << tree2.query(pos[anc], pos[anc] + 1) << '\n';
}
}
# | 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... |