이 제출은 이전 버전의 oj.uz에서 채점하였습니다. 현재는 제출 당시와는 다른 서버에서 채점을 하기 때문에, 다시 제출하면 결과가 달라질 수도 있습니다.
# include <bits/stdc++.h>
using namespace std;
#define f first
#define s second
//#define int long long
#define ll long long
#define pii pair <int, int>
#define pb push_back
#define ai3 array <int, 3>
const int N = 3e5 + 5;
int n, m, q,in[N], a[N], out[N], tin, lv[N], par[N][20];
vector <int> v[N];
vector < pii > updates;
void dfs(int a, int p) {
in[a] = ++tin;
lv[a] = lv[p] + 1;
par[a][0] = p;
for (int i = 1; i <= 18; i++) {
par[a][i] = par[par[a][i - 1]][i - 1];
}
for (int to : v[a]) {
if (to == p) continue;
dfs(to, a);
}
out[a] = tin;
}
int upper(int a, int b) {
return (in[a] <= in[b] && out[a] >= out[b]);
}
int lca(int a, int b) {
if (upper(a, b)) return a;
for (int i = 18; i >= 0; i--) {
if (par[a][i] && !upper(par[a][i], b)) a = par[a][i];
}
return par[a][0];
}
bool cmp(int a, int b) {
return in[a] < in[b];
}
int parent[N], added[N],added1[N];
vector <int> g[N];
void dfs1(int a, int p) {
parent[a] = p;
for (int to : g[a]) {
if (to == p) continue;
dfs1(to, a);
}
}
int tree[N];
void upd(int idx, int val) {
updates.pb({idx, val});
for (int i = idx; i < N; i+=i&(-i)) {
tree[i] += val;
}
}
int getans(int idx) {
int pas = 0;
for (int i = idx; i > 0; i-=i&(-i)) {
pas += tree[i];
}
return pas;
}
vector <ai3> cur_q[N];
int sum[N], ans[N];
void solve(int l, int r, vector <ai3> que) {
if (l > r || !que.size()) return ;
vector <ai3> quel, quer;
int mid = (l + r) / 2;
for (ai3 sth : que) {
if (sth[0] > mid) quer.pb(sth);
else if (sth[1] <= mid) quel.pb(sth);
else cur_q[sth[1]].pb(sth);
}
// building virtual tree, (not the most efficient way)
vector <int> vert, fv;
for (int i = l; i <= r; i++) {
vert.pb(a[i]);
}
// remove duplicates, sort by in
sort(vert.begin(), vert.end()); vert.resize(unique(vert.begin(), vert.end()) - vert.begin()); sort(vert.begin(), vert.end(), cmp);
int sz = (int)vert.size();
for (int i = 1; i < sz; i++) {
vert.pb(lca(vert[i - 1], vert[i]));
}
sort(vert.begin(), vert.end()); vert.resize(unique(vert.begin(), vert.end()) - vert.begin()); sort(vert.begin(), vert.end(), cmp);
for (int i = 1; i < (int)vert.size(); i++) { // Virtual tree edges
int lc = lca(vert[i - 1], vert[i]);
g[lc].pb(vert[i]); g[vert[i]].pb(lc);
}
dfs1(a[mid], 0);
for (int x : vert) {
added[x] = 0; added1[x] = 0;
}
sum[mid] = 0; added[a[mid]] = added1[a[mid]] = mid;
for (int i = mid - 1; i >= l; i--) {
int cur = a[i]; int vl = 0;
//if (l == 4 && r == 6) cout<<"--- "<<i<<"\n";
while (!added[cur]) {
added[cur] = i;
// if (l == 4 && r == 6) cout<<cur<<" "<<parent[cur]<<" "<<abs(lv[cur] - lv[parent[cur]])<<"\n";
vl += abs(lv[cur] - lv[parent[cur]]);
cur = parent[cur];
}
sum[i] = sum[i + 1] + vl;
}
for (int i = mid + 1; i <= r; i++) {
int cur = a[i];
while (!added1[cur]) {
if (added[cur] != mid) upd(added[cur] + 1, abs(lv[cur] - lv[parent[cur]]));
added1[cur] = i;
cur = parent[cur];
}
for (ai3 sth : cur_q[i]) {
ans[sth[2]] = getans(sth[0]) + sum[sth[0]];
}
cur_q[i].clear();
}
for (pii sth : updates) {
upd(sth.f, -sth.s);
}
updates.clear();
for (int x : vert) g[x].clear();
solve(l, mid, quel);
solve(mid + 1, r, quer);
}
signed main() {
std::ios_base::sync_with_stdio(false),cin.tie(0),cout.tie(0);
cin>>n>>m>>q;
for (int i = 1; i <= n - 1; i++) {
int a, b;
cin>>a>>b;
v[a].pb(b);
v[b].pb(a);
}
dfs(1, 0);
for (int i = 1; i <= m; i++) {
cin>>a[i];
}
vector < ai3 > queries;
for (int i = 1; i <= q; i++) {
int l, r;
cin>>l>>r;
if (l == r) ans[i] = 0;
else
queries.pb({l, r, i});
}
solve(1, m, queries);
for (int i = 1; i <= q; i++) {
cout<<ans[i] + 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... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |