제출 #851502

#제출 시각아이디문제언어결과실행 시간메모리
851502IBoryTourism (JOI23_tourism)C++17
0 / 100
5040 ms23708 KiB
#include <bits/stdc++.h> #define pii pair<int, int> using namespace std; const int SZ = 1 << 17, MAX = 100007; vector<int> G[MAX], TG[MAX]; int in[MAX], out[MAX], P[MAX], Z[MAX], H[MAX], top[MAX], dn; int C[MAX], ans[MAX]; void DFS1(int cur, int prev) { P[cur] = prev; in[cur] = ++dn; for (int next : TG[cur]) { if (next == prev) continue; G[cur].push_back(next); DFS1(next, cur); } out[cur] = dn; } int DFS2(int cur) { int& ret = Z[cur] = 1; for (int& next : G[cur]) { H[next] = H[cur] + 1; ret += DFS2(next); if (Z[next] > Z[G[cur][0]]) swap(next, G[cur][0]); } return ret; } void DFS3(int cur) { for (int next : G[cur]) { top[next] = (next == G[cur][0] ? top[cur] : next); DFS3(next); } } struct Seg { pii T[SZ << 1]; int Z[SZ << 1]; void Init(int N) { for (int i = 1; i <= N; ++i) T[i + SZ - 1] = {0, 1}; for (int i = SZ - 1; i > 0; --i) T[i] = Merge(T[i * 2], T[i * 2 + 1]); } pii Merge(pii a, pii b) { if (a.first != b.first) return min(a, b); return {a.first, a.second + b.second}; } void Push(int n) { if (!Z[n]) return; if (n < SZ) { Z[n * 2] += Z[n]; Z[n * 2 + 1] += Z[n]; } T[n].first += Z[n]; Z[n] = 0; } void Update(int L, int R, int v, int sL = 1, int sR = SZ, int n = 1) { Push(n); if (R < sL || sR < L) return; if (L <= sL && sR <= R) { Z[n] += v; Push(n); return; } int mid = (sL + sR) >> 1; Update(L, R, v, sL, mid, n * 2); Update(L, R, v, mid + 1, sR, n * 2 + 1); T[n] = Merge(T[n * 2], T[n * 2 + 1]); } pii Query(int L, int R, int sL = 1, int sR = SZ, int n = 1) { Push(n); if (R < sL || sR < L) return {1 << 30, 0}; if (L <= sL && sR <= R) return T[n]; int mid = (sL + sR) >> 1; return Merge(Query(L, R, sL, mid, n * 2), Query(L, R, mid + 1, sR, n * 2 + 1)); } void PathUpdate(int a, int b, int v) { while (top[a] != top[b]) { if (top[a] > top[b]) swap(a, b); Update(in[top[b]], in[b], v); b = P[top[b]]; } if (H[a] > H[b]) swap(a, b); Update(in[a], in[b], v); } } T; int LCA(int a, int b) { if (!min(a, b)) return max(a, b); while (top[a] != top[b]) { if (top[a] > top[b]) swap(a, b); b = P[top[b]]; } return (H[a] > H[b] ? b : a); } struct Seg2 { int T[SZ << 1]; void Build() { for (int i = SZ - 1; i > 0; --i) T[i] = LCA(T[i * 2], T[i * 2 + 1]); } int Query(int L, int R, int sL = 1, int sR = SZ, int n = 1) { if (R < sL || sR < L) return 0; if (L <= sL && sR <= R) return T[n]; int mid = (sL + sR) >> 1; return LCA(Query(L, R, sL, mid, n * 2), Query(L, R, mid + 1, sR, n * 2 + 1)); } } T2; void Add(int n) { T.PathUpdate(1, C[n], 1); } void Sub(int n) { T.PathUpdate(1, C[n], -1); } struct Query { int s, e, id; Query(int s = 0, int e = 0, int id = 0) : s(s), e(e), id(id) {}; bool operator<(const Query& a) { if ((s >> 8) != (a.s >> 8)) return (s >> 8) < (a.s >> 8); return e < a.e; } }; int main() { ios::sync_with_stdio(0); cin.tie(0); int N, M, Q; cin >> N >> M >> Q; for (int i = 1; i < N; ++i) { int a, b; cin >> a >> b; TG[a].push_back(b); TG[b].push_back(a); } DFS1(1, 0); DFS2(1); top[1] = 1; DFS3(1); for (int i = 1; i <= M; ++i) { cin >> C[i]; T2.T[SZ + i - 1] = C[i]; } T2.Build(); vector<Query> A; for (int i = 0; i < Q; ++i) { int l, r; cin >> l >> r; A.push_back(Query(l, r, i)); } sort(A.begin(), A.end()); T.Init(N); int L = 1, R = 0; for (auto [l, r, id] : A) { while (R < r) Add(++R); while (r < R) Sub(R--); while (l < L) Add(--L); while (L < l) Sub(L++); int root = T2.Query(l, r), cur = out[root] - in[root] + 1; pii p = T.Query(in[root], out[root]); if (!p.first) cur -= p.second; ans[id] = cur; } for (int i = 0; i < Q; ++i) cout << ans[i] << '\n'; return 0; }
#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...