제출 #909543

#제출 시각아이디문제언어결과실행 시간메모리
909543daoquanglinh2007Birthday gift (IZhO18_treearray)C++17
30 / 100
4046 ms35252 KiB
#include <bits/stdc++.h> using namespace std; #define pii pair <int, int> #define fi first #define se second #define mp make_pair const int NM = 2e5, LOG = 18, BL = 1000; int n, m, q; vector <int> adj[NM+5]; int dep[NM+5], timer = 0, tin[NM+5], tout[NM+5]; pii f[LOG+5][2*NM+5]; int lg[2*NM+5]; int a[NM+5], g[NM/BL+5]; bool ok[NM/BL+5][NM+5]; int pref[NM+5], suff[NM+5]; vector <int> arr[NM/BL+5]; void dfs(int u, int p){ dep[u] = (p == -1 ? 0 : dep[p]+1); tin[u] = ++timer; f[0][timer] = mp(dep[u], u); for (int v : adj[u]){ if (v == p) continue; dfs(v, u); f[0][++timer] = mp(dep[u], u); } tout[u] = timer; } void build_sparse(){ for (int i = 1; i <= LOG; i++) for (int j = 1; j+(1<<i)-1 <= timer; j++) f[i][j] = min(f[i-1][j], f[i-1][j+(1<<(i-1))]); lg[1] = 0; for (int i = 2; i <= timer; i++) lg[i] = lg[i>>1]+1; } int lca(int u, int v){ int l = tin[u], r = tin[v]; if (l > r) swap(l, r); int k = __lg(r-l+1); return min(f[k][l], f[k][r-(1<<k)+1]).se; } void build(int id){ for (int v : arr[id]) ok[id][v] = 0; arr[id].clear(); for (int i = id*BL; i < min((id+1)*BL, m); i++){ int cur = a[i]; for (int j = i; j < min((id+1)*BL, m); j++){ cur = lca(cur, a[j]); if (!ok[id][cur]){ ok[id][cur] = 1; arr[id].push_back(cur); } } if (i == id*BL) g[id] = cur; } pref[id*BL] = a[id*BL]; for (int i = id*BL+1; i < min((id+1)*BL, m); i++) pref[i] = lca(pref[i-1], a[i]); suff[min((id+1)*BL, m)-1] = a[min((id+1)*BL, m)-1]; for (int i = min((id+1)*BL, m)-2; i >= id*BL; i--) suff[i] = lca(suff[i+1], a[i]); } void preprocess(){ for (int i = 0; i*BL < m; i++){ build(i); } } void update(int x, int val){ a[x] = val; build(x/BL); } bool is_ancestor(int a, int u){ return tin[a] <= tin[u] && tout[a] >= tout[u]; } pii manual_query(int l, int r, int v){ for (int i = l; i <= r; i++) if (is_ancestor(v, a[i])){ int cur = a[i], j = i; while (j < r){ int ne = lca(cur, a[j+1]); if (is_ancestor(v, ne)){ cur = ne; j++; } else break; } if (cur == v) return mp(i, j); i = j; } return mp(-1, -1); } pii query(int l, int r, int v){ int L = (l+BL-1)/BL, R = (r-BL+1)/BL; if (l/BL == r/BL || L > R){ return manual_query(l, r, v); } for (int i = L; i <= R; i++) if (ok[i][v]){ return manual_query(i*BL, min((i+1)*BL, m)-1, v); } pii tmp = manual_query(l, L*BL-1, v); if (tmp.fi != -1) return tmp; tmp = manual_query((R+1)*BL, r, v); if (tmp.fi != -1) return tmp; for (int i = L; i <= R+1; i++) if (i <= R && is_ancestor(v, g[i])){ int j = i, cur = g[i]; while (j < R){ int ne = lca(cur, g[j+1]); if (is_ancestor(v, ne)){ cur = ne; j++; } else break; } int lo = max(l, (i-1)*BL), hi = i*BL-1, resl = i*BL; while (lo <= hi){ int mid = (lo+hi)/2; if (is_ancestor(v, suff[mid])){ resl = mid; hi = mid-1; } else lo = mid+1; } if (resl < i*BL) cur = lca(cur, suff[resl]); lo = (j+1)*BL, hi = min(r, (j+2)*BL-1); int resr = (j+1)*BL-1; while (lo <= hi){ int mid = (lo+hi)/2; if (is_ancestor(v, pref[mid])){ resr = mid; lo = mid+1; } else hi = mid-1; } if (resr >= (j+1)*BL) cur = lca(cur, pref[resr]); if (cur == v) return mp(resl, resr); i = j; } else{ int lo = max(l, (i-1)*BL), hi = min(r, i*BL-1), resl = -1; while (lo <= hi){ int mid = (lo+hi)/2; if (is_ancestor(v, suff[mid])){ resl = mid; hi = mid-1; } else lo = mid+1; } lo = max(l, i*BL), hi = min(r, (i+1)*BL-1); int resr = -1; while (lo <= hi){ int mid = (lo+hi)/2; if (is_ancestor(v, pref[mid])){ resr = mid; lo = mid+1; } else hi = mid-1; } if (resl != -1 && resr != -1){ if (lca(suff[resl], pref[resr]) == v){ return mp(resl, resr); } } } return mp(-1, -1); } int main(){ ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0); cin >> n >> m >> q; for (int i = 1; i < n; i++){ int u, v; cin >> u >> v; adj[u].push_back(v); adj[v].push_back(u); } dfs(1, -1); build_sparse(); for (int i = 0; i < m; i++) cin >> a[i]; preprocess(); while (q--){ int type; cin >> type; if (type == 1){ int pos, val; cin >> pos >> val; update(pos-1, val); } else{ int l, r, v; cin >> l >> r >> v; pii ans = query(l-1, r-1, v); if (ans.fi != -1){ int cur = a[ans.fi]; for (int i = ans.fi+1; i <= ans.se; i++) cur = lca(cur, a[i]); ans.fi++, ans.se++; } cout << ans.fi << ' ' << ans.se << '\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...