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 <bits/stdc++.h>
using namespace std;
const int INIT = (1 << 17) - 1;
int sommes[(1 << 18)];
void ajoute(int pos, int val) {
pos += (1 << 17);
while(pos != 0) {
sommes[pos] += val;
pos /= 2;
}
}
int somme_entre(int deb, int fin) {
deb += (1 << 17);
fin += (1 << 17);
int somme = 0;
while(deb < fin) {
if(deb % 2 == 1) {
somme += sommes[deb];
deb++;
}
if(fin % 2 == 1) {
fin--;
somme += sommes[fin];
}
deb /= 2;
fin /= 2;
}
return somme;
}
struct Req {
int deb, fin, id;
};
struct Inter {
int deb, fin, couleur;
};
int N, M, Q;
vector<int> voisins[100 * 1000];
vector<int> positions;
vector<Req> reqs[100 * 1000];
int reponses[100 * 1000];
int profs[100 * 1000];
int posPeigne;
int gauches[100 * 1000];
int droites[100 * 1000];
int remontes[20][100 * 1000];
int id_chaine[100 * 1000];
vector<vector<Inter>> chaines;
bool est_parent(int u, int v) {
return gauches[u] <= gauches[v] && droites[v] <= droites[u];
}
bool est_parent_strict(int u, int v) {
if(u == -1) return true;
return gauches[u] < gauches[v] && droites[v] < droites[u];
}
pair<int, int> up(pair<int, int> a, pair<int, int> b) {
int l, r;
if(gauches[a.first] < gauches[b.first])
l = a.first;
else
l = b.first;
if(gauches[a.second] < gauches[b.second])
r = b.second;
else
r = a.second;
return {l, r};
}
pair<int, int> arbre_dfs[(1 << 18)];
pair<int, int> get_bords(int deb, int fin) {
pair<int, int> sol = {positions[deb], positions[deb]};
deb += (1 << 17);
fin += (1 << 17);
while(deb < fin) {
if(deb % 2 == 1) {
sol = up(sol, arbre_dfs[deb]);
deb++;
}
if(fin % 2 == 1) {
fin--;
sol = up(sol, arbre_dfs[fin]);
}
deb /= 2;
fin /= 2;
}
return sol;
}
int build_ds(int u, int p = -1, int prof = 0) {
remontes[0][u] = p;
profs[u] = prof;
gauches[u] = posPeigne++;
int taille = 1;
pair<int, int> mel_fils = {-1, -1};
for(int v : voisins[u]) {
if(v == p) continue;
int ret = build_ds(v, u, prof + 1);
taille += ret;
mel_fils = max(mel_fils, {ret, id_chaine[v]});
}
if(mel_fils.first == -1) {
id_chaine[u] = chaines.size();
chaines.push_back({});
chaines.back().push_back({p, u, INIT});
}
else {
id_chaine[u] = mel_fils.second;
chaines[mel_fils.second].push_back({p, u, INIT});
}
droites[u] = posPeigne++;
return taille;
}
int lca(int u, int v) {
if(est_parent(u, v)) return u;
for(int rem = 19;rem >= 0;rem--) {
int w = remontes[rem][u];
if(w != -1 && !est_parent(w, v)) {
u = w;
}
}
return remontes[0][u];
}
int get_prof(int u) {
if(u == -1) return -1;
return profs[u];
}
void recolorie(int u, int color) {
while(u != -1) {
vector<Inter>& chaine = chaines[id_chaine[u]];
int start = chaine.back().deb;
int end;
int last_col;
while(!chaine.empty()
&& est_parent_strict(chaine.back().deb, u)) {
end = chaine.back().fin;
last_col = chaine.back().couleur;
int sz = get_prof(chaine.back().fin)
- get_prof(chaine.back().deb);
int col = chaine.back().couleur;
ajoute(col, -sz);
chaine.pop_back();
}
if(u != end) {
chaine.push_back({u, end, last_col});
ajoute(last_col,
get_prof(end)
- get_prof(u)
);
}
chaine.push_back({start, u, color});
ajoute(color,
get_prof(u)
- get_prof(start)
);
u = start;
}
}
void solve() {
build_ds(0);
for(int prof = 1;prof < 20;prof++) {
for(int i = 0;i < N;i++) {
if(remontes[prof - 1][i] == -1)
remontes[prof][i] = -1;
else
remontes[prof][i] = remontes[prof - 1][
remontes[prof - 1][i]
];
}
}
for(int i = 0;i < M;i++) {
arbre_dfs[(1 << 17) + i] = {positions[i], positions[i]};
}
for(int i = (1 << 17) - 1;i > 0;i--) {
arbre_dfs[i] = up(arbre_dfs[2 * i], arbre_dfs[2 * i + 1]);
}
for(int l = M - 1;l >= 0;l--) {
recolorie(positions[l], l);
for(Req r : reqs[l]) {
int res = somme_entre(l, r.fin);
pair<int, int> bords = get_bords(l, r.fin);
res -= profs[lca(
bords.first, bords.second
)];
reponses[r.id] = res;
}
}
}
int main() {
ios_base::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
cin >> N >> M >> Q;
for(int i = 0;i < N - 1;i++) {
int deb, fin;
cin >> deb >> fin;
deb--; fin--;
voisins[deb].push_back(fin);
voisins[fin].push_back(deb);
}
for(int i = 0;i < M;i++) {
int pos;
cin >> pos;
pos--;
positions.push_back(pos);
}
for(int i = 0;i < Q;i++) {
int deb, fin;
cin >> deb >> fin;
deb--;
reqs[deb].push_back({deb, fin, i});
}
solve();
for(int i = 0;i < Q;i++) {
cout << reponses[i] << endl;
}
return 0;
}
Compilation message (stderr)
tourism.cpp: In function 'void recolorie(int, int)':
tourism.cpp:9:6: warning: 'last_col' may be used uninitialized in this function [-Wmaybe-uninitialized]
9 | pos += (1 << 17);
| ~~~~^~~~~~~~~~~~
tourism.cpp:165:7: note: 'last_col' was declared here
165 | int last_col;
| ^~~~~~~~
tourism.cpp:156:16: warning: 'end' may be used uninitialized in this function [-Wmaybe-uninitialized]
156 | return profs[u];
| ^
tourism.cpp:164:7: note: 'end' was declared here
164 | int end;
| ^~~
# | 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... |