제출 #1067995

#제출 시각아이디문제언어결과실행 시간메모리
1067995vjudge1Dynamic Diameter (CEOI19_diameter)C++17
0 / 100
5061 ms20892 KiB
#include <bits/stdc++.h> #define ll long long using namespace std; const int N = 1e5 + 16; int n, q, W, u, v; ll w, result; vector < pair <int, ll> > adj[N]; vector <int> id[N]; /* 4 3 2000 1 2 100 2 3 1000 2 4 1000 2 1030 1 1020 1 890 */ /* 10 10 10000 1 9 1241 5 6 1630 10 5 1630 2 6 853 10 1 511 5 3 760 8 3 1076 4 10 1483 7 10 40 8 2051 5 6294 5 4168 7 1861 0 5244 6 5156 3 3001 8 5267 5 3102 8 3623 */ ll a[N]; int h[N], par[N], sz[N], edge[N]; int chainHead[N], chainId[N], chainArr[N], pos[N], curPos = 1, curChain = 1; void dfs(int k, int p) { sz[k] = 1; int i = -1; for (auto v : adj[k]) { i++; if (v.first == p) { continue; } edge[id[k][i]] = v.first; a[v.first] = v.second; h[v.first] = h[k] + 1; par[v.first] = k; dfs(v.first, k); sz[k] += sz[v.first]; } } void hld(int k, int p) { if (!chainHead[curChain]) { chainHead[curChain] = k; } chainId[k] = curChain; pos[k] = curPos; chainArr[curPos] = k; curPos++; int heaviest = 0; for (auto v : adj[k]) { if (v.first == p) { continue; } if (heaviest == 0 || sz[v.first] > sz[heaviest]) { heaviest = v.first; } } if (heaviest) { hld(heaviest, k); } for (auto v : adj[k]) { if (v.first == p || v.first == heaviest) { continue; } curChain++; hld(v.first, k); } } int lca(int u, int v) { while (chainId[u] != chainId[v]) { if (chainId[u] > chainId[v]) { u = par[chainHead[chainId[u]]]; } else { v = par[chainHead[chainId[v]]]; } } if (h[u] < h[v]) { return u; } return v; } ll segmentTree[4 * N]; void build(int k, int l, int r) { if (l == r) { segmentTree[k] = a[chainArr[l]]; return; } int mid = (l + r) / 2; build(2 * k, l, mid); build(2 * k + 1, mid + 1, r); segmentTree[k] = segmentTree[2 * k] + segmentTree[2 * k + 1]; } void update(int k, int l, int r, int x, ll y) { if (l > x || x > r) { return; } if (l == r) { segmentTree[k] = y; return; } int mid = (l + r) / 2; update(2 * k, l, mid, x, y); update(2 * k + 1, mid + 1, r, x, y); segmentTree[k] = segmentTree[2 * k] + segmentTree[2 * k + 1]; } ll get(int k, int l, int r, int x, int y) { if (l > y || x > r) { return 0; } if (l >= x && r <= y) { return segmentTree[k]; } int mid = (l + r) / 2; return get(2 * k, l, mid, x, y) + get(2 * k + 1, mid + 1, r, x, y); } void updateTree(int id, ll val) { update(1, 1, curPos, pos[edge[id]], val); } ll getTree(int u, int v) { int LCA = lca(u, v); ll ans = 0; while (chainId[u] != chainId[LCA]) { ans = get(1, 1, curPos, pos[chainHead[chainId[u]]], pos[u]) + ans; u = par[chainHead[chainId[u]]]; } while (chainId[v] != chainId[LCA]) { ans = get(1, 1, curPos, pos[chainHead[chainId[v]]], pos[v]) + ans; v = par[chainHead[chainId[v]]]; } if (h[u] < h[v]) { ans = get(1, 1, curPos, pos[u] + 1, pos[v]) + ans; } else { ans = get(1, 1, curPos, pos[v] + 1, pos[u]) + ans; } return ans; } int parCd[N], szCd[N]; bool visited[N]; void countChild(int k, int p) { szCd[k] = 1; for (auto v : adj[k]) { if (visited[v.first] || v.first == p) { continue; } countChild(v.first, k); szCd[k] += szCd[v.first]; } } int findCentroid(int k, int p, int treeSz) { for (auto v : adj[k]) { if (visited[v.first] || v.first == p) { continue; } if (sz[v.first] > treeSz / 2) { return findCentroid(v.first, k, treeSz); } } return k; } void cd(int k, int p) { countChild(k, k); int centroid = findCentroid(k, k, sz[k]); visited[centroid] = true; parCd[centroid] = p; for (auto v : adj[centroid]) { if (!visited[v.first]) { cd(v.first, centroid); } } } multiset < pair <ll, int> > s[N]; void updateCentroid(int k) { int v = k, p = k; while (v) { bool sameSub = false; for (auto x : s[v]) { if (x.second != p) { continue; } sameSub = true; ll dist = getTree(k, v); if (dist > x.first) { s[v].erase(x); s[v].insert({dist, p}); break; } } if (!sameSub) { s[v].insert({getTree(k, v), p}); if (s[v].size() > 2) { s[v].erase(s[v].begin()); } } p = v; v = parCd[v]; } } ll getCentroid(int k) { ll ans = 0; int v = k, p = k; while (v) { for (auto x : s[v]) { if (x.second != p) { ans = max(ans, x.first + getTree(k, v)); } } p = v; v = parCd[v]; } return ans; } pair <int, int> e[N]; void removeCentroid(int k) { int v = k, p = k; while (v) { pair <ll, int> val = {getTree(k, v), p}; if (s[v].find(val) != s[v].end()) { s[v].erase(s[v].find(val)); } p = v; v = parCd[v]; } } void updateAll(int id, ll val) { u = e[id].first; v = e[id].second; removeCentroid(u); removeCentroid(v); updateTree(id, val); updateCentroid(u); updateCentroid(v); } int main() { ios_base :: sync_with_stdio(false); cin.tie(0); cout.tie(0); cin >> n >> q >> W; for (int i = 1; i < n; i++) { cin >> u >> v >> w; adj[u].push_back({v, w}); adj[v].push_back({u, w}); id[u].push_back(i); id[v].push_back(i); e[i] = {u, v}; } dfs(1, 1); hld(1, 1); build(1, 1, curPos); cd(1, 0); for (int i = 1; i <= n; i++) { updateCentroid(i); } while (q--) { int d, f; cin >> d >> f; d = 1 + (d + result) % (n - 1); f = (f + result) % W; updateAll(d, f); result = 0; for (int i = 1; i <= n; i++) { result = max(result, getCentroid(i)); } cout << result << "\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...