#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
const int N = 1e5 + 50, logN = 30;
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], anc[N][logN + 1], 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];
// }
// if (tree1.query(pos[u], pos[u] + 1) == 0) {
// return 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 kth_ancesor(int u, int k) {
for (int pow = 0; pow <= logN; pow++) {
if ((k & (1 << pow)) != 0) {
u = anc[u][pow];
if (u == -1) break;
}
}
return u;
}
int query1(int u, int v) {
// for (; root[x] != root[y]; y = par[root[y]]) {
// if (depth[root[x]] > depth[root[y]]) swap(x,y);
// op(pos[root[y]],pos[y]);
// }
// if (depth[x] > depth[y]) swap(x,y);
// op(pos[x] + 1, pos[y]);
int res = 0;
for (; root[u] != root[v]; v = par[root[v]]) {
if (depth[root[u]] > depth[root[v]]) swap(u, v);
res += tree1.query(pos[root[v]], pos[v] + 1);
}
if (depth[u] > depth[v]) swap(u, v);
res += tree1.query(pos[u], pos[v] + 1);
return res;
}
void query2(int u, int v) {
// int s = u;
// int dif = tree2.query(pos[u], pos[u] + 1) - last[u];
// while(depth[v] < depth[root[u]]) {
// tree2.add(pos[root[u]], pos[u] + (u != s), dif);
// u = par[root[u]];
// }
// tree2.add(pos[v], pos[u], dif);
int dif = tree2.query(pos[u], pos[u] + 1) - last[u];
for (; root[u] != root[v]; v = par[root[v]]) {
if (depth[root[u]] > depth[root[v]]) swap(u, v);
tree2.add(pos[root[v]], pos[v] + 1, dif);
}
if (depth[u] > depth[v]) swap(u, v);
tree2.add(pos[u], pos[v] + 1, dif);
}
int highest_ancesor(int u) {
int l = 0, r = depth[u];
while(r - l > 1) {
int mid = (r + l) / 2;
int v = kth_ancesor(u, mid);
if (v == -1 || query1(u, v) != depth[u] - depth[v]) {
r = mid;
} else {
l = mid;
}
}
int res = kth_ancesor(u, l);
return (res == -1 ? u : res);
}
int main()
{
// ifstfream cin("input.txt");
// ostream 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);
anc[0][0] = -1;
for (int i = 0; i < n; i++) anc[i][0] = par[i];
for (int j = 1; j <= logN; j++) {
anc[0][j] = -1;
for (int i = 1; i < n; i++) {
if (anc[i][j - 1] == -1) {
anc[i][j] = -1;
continue;
}
anc[i][j] = anc[anc[i][j - 1]][j - 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);
query2(u, highest_ancesor(u));
} else {
int anc = highest_ancesor(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 = highest_ancesor(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... |