제출 #970526

#제출 시각아이디문제언어결과실행 시간메모리
970526vjudge1Tourism (JOI23_tourism)C++17
100 / 100
254 ms27280 KiB
#include<bits/stdc++.h> #define ll long long #define task "" using namespace std; const int maxn = 1e5 + 4; int n, m, a, b, q, l, r, fw[maxn], city[maxn], res[maxn]; int par[maxn], sz[maxn], dep[maxn], nxt[maxn]; int curchain = 1, curpos = 0, head[maxn], chain[maxn], pos[maxn]; bool visited[maxn]; vector<int> adj[maxn]; vector<pair<int, int>> query[maxn]; //basic hld :3 void dfs (int u) { sz[u] = 1; visited[u] = true; for (int v : adj[u]) if (!visited[v]) { par[v] = u; dep[v] = dep[u] + 1; dfs(v); sz[u] += sz[v]; if (nxt[u] == 0 || sz[v] > sz[nxt[u]]) nxt[u] = v; } } void hld (int u) { if (!head[curchain]) head[curchain] = u; chain[u] = curchain; pos[u] = ++curpos; if (nxt[u] != 0) hld(nxt[u]); for (int v : adj[u]) if (v != par[u] && v != nxt[u]) { curchain++; hld(v); } } //fenwick tree to answer the queries void upd (int idx, int val) { while (idx <= m) { fw[idx] += val; idx += (idx & (-idx)); } } int get (int idx) { int res = 0; while (idx > 0) { res += fw[idx]; idx -= (idx & (-idx)); } return res; } //updating the path from u to v with the corresponding time struct Event { int l, r, t; bool operator < (const Event& other) const { return l < other.l; } }; multiset<Event> line[maxn]; //each multiset manages a chain (hopefully i understand this correctly) void update (int u, int v, int t) { while (chain[u] != chain[v]) { if (chain[u] < chain[v]) swap(u, v); Event e = {pos[head[chain[u]]], pos[u], t}; int id = chain[u]; while (!line[id].empty()) { auto it = line[id].begin(); Event f = *it; if (f.l > e.r) break; upd(f.t, -(f.r - f.l + 1)); line[id].erase(it); if (f.r > e.r) { f.l = e.r + 1; line[id].insert(f); upd(f.t, f.r - e.r); } //remember the event e always start at the head of the chain so e.l <= f.l } upd(e.t, e.r - e.l + 1); line[id].insert(e); u = par[head[chain[u]]]; } if (pos[u] > pos[v]) swap(u, v); Event e = {pos[u], pos[v], t}; int id = chain[u]; while (!line[id].empty()) { auto it = line[id].upper_bound(e); if (it == line[id].begin()) break; it--; Event f = *it; if (f.r < e.l) break; upd(f.t, -(f.r - f.l + 1)); line[id].erase(it); if (f.r > e.r) { int prevfl = f.l; f.l = e.r + 1; upd(f.t, f.r - e.r); line[id].insert(f); f.r = e.r; f.l = prevfl; } if (f.l < e.l) { f.r = e.l - 1; upd(f.t, f.r - f.l + 1); line[id].insert(f); } } while (!line[id].empty()) { auto it = line[id].lower_bound(e); if (it == line[id].end()) break; Event f = *it; if (f.l > e.r) break; upd(f.t, -(f.r - f.l + 1)); line[id].erase(it); if (f.r > e.r) { f.l = e.r + 1; upd(f.t, f.r - f.l + 1); line[id].insert(f); } //again, e.l <= f.l } upd(e.t, e.r - e.l + 1); line[id].insert(e); } int main () { //freopen(task".INP", "r", stdin); //freopen(task".OUT", "w", stdout); ios_base::sync_with_stdio(0); cin.tie(0); cin >> n >> m >> q; for (int i = 1; i < n; i++) { cin >> a >> b; adj[a].push_back(b); adj[b].push_back(a); } for (int i = 1; i <= m; i++) cin >> city[i]; for (int i = 1; i <= q; i++) { cin >> l >> r; if (l == r) res[i] = 1; else query[r].push_back({l, i}); } dfs(1); hld(1); for (int i = 2; i <= m; i++) { update(city[i], city[i - 1], i - 1); for (pair<int, int> p : query[i]) res[p.second] = get(i) - get(p.first - 1); } for (int i = 1; i <= q; i++) cout << res[i] << '\n'; }
#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...