This submission is migrated from previous version of oj.uz, which used different machine for grading. This submission may have different result if resubmitted.
#include <algorithm>
#include <iostream>
#include <numeric>
#include <cassert>
#include <vector>
#include <stack>
#include <cmath>
#pragma GCC optimize ("O3")
#pragma GCC target ("sse4")
typedef long long llong;
const int MAXN = 100000 + 10;
const int MAXLOG = 18;
const int INF = 1e9;
int n, m, q;
int in[MAXN];
int out[MAXN];
int globalCost;
bool isInC[MAXN];
std::vector <int> notInC;
std::vector <int> inTimes;
int cnt[2 * MAXN];
int c[MAXN];
struct LinkedList
{
struct Sparse
{
int sparse[MAXLOG][2 * MAXN];
std::vector <int> tour;
int getLog[2 * MAXN];
int depth[MAXN];
int cmp(int x, int y)
{
if (depth[x] < depth[y]) return x;
else return y;
}
void build(std::vector <int> _tour, int dep[])
{
tour = _tour;
for (int i = 1 ; i <= n ; ++i)
{
depth[i] = dep[i];
}
for (int i = 1 ; i < tour.size() ; ++i)
{
sparse[0][i] = tour[i];
}
for (int lg = 1 ; (1 << lg) <= tour.size() ; ++lg)
{
for (int i = 1 ; i + (1 << lg) - 1 < tour.size() ; ++i)
{
sparse[lg][i] = cmp(sparse[lg - 1][i], sparse[lg - 1][i + (1 << lg - 1)]);
}
}
for (int i = 1 ; i <= tour.size() ; ++i)
{
getLog[i] = getLog[i - 1];
if ((1 << getLog[i] + 1) < i) getLog[i]++;
}
}
int findLCA(int l, int r)
{
int lg = getLog[r - l + 1];
return cmp(sparse[lg][l], sparse[lg][r - (1 << lg) + 1]);
}
int findDist(int u, int v)
{
if (in[u] > in[v])
{
std::swap(u, v);
}
return depth[u] + depth[v] - 2 * depth[findLCA(in[u], in[v])];
}
};
struct RollElementCnt
{
int idx;
int time;
int value;
};
struct RollElement
{
int idx;
int value;
};
int answer;
int prev[2 * MAXN];
int next[2 * MAXN];
int prev2[2 * MAXN];
int next2[2 * MAXN];
int answer2;
std::stack <RollElement> stNext;
std::stack <RollElement> stPrev;
std::stack <RollElementCnt> stCnt;
std::stack <int> stAnswer;
std::stack <int> stTime;
std::vector <int> tour;
Sparse sparse;
int timer;
void build(std::vector <int> _tour, int depth[])
{
tour = _tour;
sparse.build(tour, depth);
}
void fix()
{
int ptr = 0;
for (int i = 0 ; i <= tour.size() ; ++i)
{
while (inTimes[ptr] <= i)
{
ptr++;
}
next[i] = inTimes[ptr];
}
ptr = inTimes.size() - 1;
for (int i = tour.size() ; i >= 0 ; --i)
{
while (inTimes[ptr] >= i)
{
ptr--;
}
prev[i] = inTimes[ptr];
}
std::fill(cnt, cnt + 1 + 2 * n, 0);
for (int i = 1 ; i <= m ; ++i)
{
cnt[in[c[i]]]++;
}
answer = 2 * n - 2 - sparse.findDist(tour[next[0]], tour[prev[tour.size()]]);
timer = 0;
for (const int &i : notInC)
{
remove(in[i]);
}
for (int i = 0 ; i <= tour.size() + 1 ; ++i)
{
prev2[i] = prev[i];
next2[i] = next[i];
}
answer2 = answer;
}
void rebuild()
{
while (stNext.size())
{
stNext.pop();
}
while (stPrev.size())
{
stPrev.pop();
}
while (stCnt.size())
{
stCnt.pop();
}
while (stAnswer.size())
{
stAnswer.pop();
}
while (stTime.size())
{
stTime.pop();
}
std::fill(cnt, cnt + 1 + 2 * n, 0);
for (int i = 1 ; i <= m ; ++i)
{
cnt[in[c[i]]]++;
}
timer = 0;
for (int i = 0 ; i <= tour.size() + 1 ; ++i)
{
prev[i] = prev2[i];
next[i] = next2[i];
}
answer = answer2;
}
void roll(int to)
{
while (stCnt.size() && stCnt.top().time > to)
{
cnt[stCnt.top().idx] = stCnt.top().value;
stCnt.pop();
}
while (stTime.size() && stTime.top() > to)
{
next[stNext.top().idx] = stNext.top().value;
prev[stPrev.top().idx] = stPrev.top().value;
answer = stAnswer.top();
stNext.pop();
stTime.pop();
stPrev.pop();
stAnswer.pop();
}
}
void remove(int idx)
{
timer++;
stCnt.push({idx, timer, cnt[idx]});
cnt[idx]--;
if (cnt[idx] > 0)
{
return;
}
int l = prev[idx];
int r = next[idx];
stTime.push(timer);
stAnswer.push(answer);
stNext.push({l, next[l]});
stPrev.push({r, prev[r]});
if (l > 0) answer -= sparse.findDist(tour[l], tour[idx]);
if (r < tour.size()) answer -= sparse.findDist(tour[idx], tour[r]);
if (l > 0 && r < tour.size()) answer += sparse.findDist(tour[l], tour[r]);
next[l] = r;
prev[r] = l;
getAnswer();
}
int getAnswer()
{
int res = answer;
res += sparse.findDist(tour[next[0]], tour[prev[tour.size()]]);
return res / 2 + 1;
}
};
int bucketSize;
LinkedList list;
struct Query
{
int l, r;
int idx;
friend bool operator < (const Query &a, const Query &b)
{
if (a.l / bucketSize != b.l / bucketSize) return a.l < b.l;
return a.r > b.r;
}
};
int depth[MAXN];
int answer[MAXN];
std::vector <int> tour;
std::vector <int> g[MAXN];
Query query[MAXN];
void buildDFS(int node, int par)
{
depth[node] = depth[par] + 1;
in[node] = tour.size();
tour.push_back(node);
for (const int &u : g[node])
{
if (u == par)
{
continue;
}
buildDFS(u, node);
tour.push_back(node);
}
out[node] = tour.size();
}
void solve()
{
bucketSize = 2 * sqrt(m) + 1;
tour.push_back(0);
buildDFS(1, 0);
for (int i = 1 ; i <= n ; ++i)
{
inTimes.push_back(in[i]);
}
inTimes.push_back(-1);
inTimes.push_back(0);
inTimes.push_back(tour.size());
inTimes.push_back(tour.size() + 1);
std::sort(inTimes.begin(), inTimes.end());
for (int i = 1 ; i <= m ; ++i)
{
isInC[c[i]] = true;
}
for (int i = 1 ; i <= n ; ++i)
{
if (!isInC[i])
{
notInC.push_back(i);
}
}
list.build(tour, depth);
list.fix();
int lPtr = 1;
int rPtr = m;
int lastBucket = -1;
std::sort(query + 1, query + 1 + q);
for (int i = 1 ; i <= q ; ++i)
{
int qL = query[i].l;
int qR = query[i].r;
if (qL / bucketSize != lastBucket)
{
lPtr = 1;
rPtr = m;
list.rebuild();
lastBucket = qL / bucketSize;
while (lPtr / bucketSize != lastBucket)
{
list.remove(in[c[lPtr]]);
lPtr++;
}
}
while (rPtr > qR)
{
list.remove(in[c[rPtr]]);
rPtr--;
}
int rollTo = list.timer;
int beforeL = lPtr;
while (lPtr < qL)
{
list.remove(in[c[lPtr]]);
lPtr++;
}
answer[query[i].idx] = list.getAnswer();
lPtr = beforeL;
list.getAnswer();
list.roll(rollTo);
list.getAnswer();
}
}
void input()
{
std::cin >> n >> m >> q;
for (int i = 1 ; i < n ; ++i)
{
int u, v;
std::cin >> u >> v;
g[u].push_back(v);
g[v].push_back(u);
}
for (int i = 1 ; i <= m ; ++i)
{
std::cin >> c[i];
}
for (int i = 1 ; i <= q ; ++i)
{
std::cin >> query[i].l >> query[i].r;
query[i].idx = i;
}
}
void print()
{
for (int i = 1 ; i <= q ; ++i)
{
std::cout << answer[i] << '\n';
}
}
void fastIOI()
{
std::ios_base :: sync_with_stdio(0);
std::cout.tie(nullptr);
std::cin.tie(nullptr);
}
int main()
{
fastIOI();
input();
solve();
print();
return 0;
}
Compilation message (stderr)
tourism.cpp: In member function 'void LinkedList::Sparse::build(std::vector<int>, int*)':
tourism.cpp:50:32: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
50 | for (int i = 1 ; i < tour.size() ; ++i)
| ~~^~~~~~~~~~~~~
tourism.cpp:55:41: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
55 | for (int lg = 1 ; (1 << lg) <= tour.size() ; ++lg)
| ~~~~~~~~~~^~~~~~~~~~~~~~
tourism.cpp:57:52: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
57 | for (int i = 1 ; i + (1 << lg) - 1 < tour.size() ; ++i)
| ~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~
tourism.cpp:59:88: warning: suggest parentheses around '-' inside '<<' [-Wparentheses]
59 | sparse[lg][i] = cmp(sparse[lg - 1][i], sparse[lg - 1][i + (1 << lg - 1)]);
| ~~~^~~
tourism.cpp:63:32: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
63 | for (int i = 1 ; i <= tour.size() ; ++i)
| ~~^~~~~~~~~~~~~~
tourism.cpp:66:37: warning: suggest parentheses around '+' inside '<<' [-Wparentheses]
66 | if ((1 << getLog[i] + 1) < i) getLog[i]++;
| ~~~~~~~~~~^~~
tourism.cpp: In member function 'void LinkedList::fix()':
tourism.cpp:126:28: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
126 | for (int i = 0 ; i <= tour.size() ; ++i)
| ~~^~~~~~~~~~~~~~
tourism.cpp:161:28: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
161 | for (int i = 0 ; i <= tour.size() + 1 ; ++i)
| ~~^~~~~~~~~~~~~~~~~~
tourism.cpp: In member function 'void LinkedList::rebuild()':
tourism.cpp:204:28: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
204 | for (int i = 0 ; i <= tour.size() + 1 ; ++i)
| ~~^~~~~~~~~~~~~~~~~~
tourism.cpp: In member function 'void LinkedList::remove(int)':
tourism.cpp:252:15: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
252 | if (r < tour.size()) answer -= sparse.findDist(tour[idx], tour[r]);
| ~~^~~~~~~~~~~~~
tourism.cpp:253:24: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
253 | if (l > 0 && r < tour.size()) answer += sparse.findDist(tour[l], tour[r]);
| ~~^~~~~~~~~~~~~
# | 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... |