Submission #781999

#TimeUsernameProblemLanguageResultExecution timeMemory
781999ArturgoTourism (JOI23_tourism)C++14
100 / 100
297 ms40748 KiB
#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 timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...