Submission #1287419

#TimeUsernameProblemLanguageResultExecution timeMemory
1287419red_soulsGrapevine (NOI22_grapevine)C++17
53 / 100
1110 ms242948 KiB
#include <bits/stdc++.h> #define ll long long #define task "GRAPEVINE" using namespace std; const int N = 1e5 + 16; const ll INF = 1e18; int n, q, u, v; ll w; vector < pair <int, ll> > adj[N]; namespace sub6 { int h[N], up[N][26], timeDfs, in[N], out[N]; ll d[N], val[N]; void dfs(int k) { timeDfs++; in[k] = timeDfs; for (auto v : adj[k]) { if (v.first == up[k][0]) { continue; } d[v.first] = d[k] + v.second; val[v.first] = v.second; h[v.first] = h[k] + 1; up[v.first][0] = k; for (int i = 1; i <= 20; i++) { up[v.first][i] = up[up[v.first][i - 1]][i - 1]; } dfs(v.first); } out[k] = timeDfs; } int lca(int u, int v) { if (h[u] != h[v]) { if (h[u] < h[v]) { swap(u, v); } int k = h[u] - h[v]; for (int i = 0; (1 << i) <= k; i++) { if (k >> i & 1) { u = up[u][i]; } } } if (u == v) { return u; } int k = __lg(h[u]); for (int i = k; i >= 0; i--) { if (up[u][i] != up[v][i]) { u = up[u][i]; v = up[v][i]; } } return up[u][0]; } bool checkSubtree(int root, int k) { return in[root] <= in[k] && out[k] <= out[root]; } bool cmp(int a, int b) { return in[a] < in[b]; } int sz[N], parCd[N]; bool visited[N]; void countChild(int k, int p) { sz[k] = 1; for (auto v : adj[k]) { if (v.first == p || visited[v.first]) { continue; } countChild(v.first, k); sz[k] += sz[v.first]; } } int findCentroid(int k, int p, int treeSz) { for (auto v : adj[k]) { if (v.first == p || visited[v.first]) { continue; } if (sz[v.first] > (treeSz >> 1)) { return findCentroid(v.first, k, treeSz); } } return k; } int cd(int k) { countChild(k, k); int centroid = findCentroid(k, k, sz[k]); visited[centroid] = true; for (auto v : adj[centroid]) { if (!visited[v.first]) { parCd[cd(v.first)] = centroid; } } return centroid; } struct node { ll d = INF, answer = INF; int state = 0; ll lazy = 0; node operator + (const node &other) const { node ans; if (answer < other.answer) { ans.d = d; ans.answer = answer; ans.state = state; } else { ans.d = other.d; ans.answer = other.answer; ans.state = other.state; } return ans; } }; struct IT { int n, root; vector <int> lst; vector <node> segmentTree; void build(int k, int l, int r) { if (l == r) { segmentTree[k].d = d[lst[l - 1]] + d[root] - 2 * d[lca(lst[l - 1], root)]; return; } int mid = l + r >> 1; build(k << 1, l, mid); build(k << 1 | 1, mid + 1, r); } void down(int k) { ll t = segmentTree[k].lazy; if (t == 0) { return; } segmentTree[k << 1].d += t; segmentTree[k << 1].answer += t; segmentTree[k << 1].answer = min(segmentTree[k << 1].answer, INF); segmentTree[k << 1].lazy += t; segmentTree[k << 1 | 1].d += t; segmentTree[k << 1 | 1].answer += t; segmentTree[k << 1 | 1].answer = min(segmentTree[k << 1 | 1].answer, INF); segmentTree[k << 1 | 1].lazy += t; segmentTree[k].lazy = 0; } void updateRange(int k, int l, int r, int x, int y, ll w) { if (l > y || x > r) { return; } if (l >= x && r <= y) { segmentTree[k].d += w; segmentTree[k].answer += w; segmentTree[k].answer = min(segmentTree[k].answer, INF); segmentTree[k].lazy += w; return; } int mid = l + r >> 1; down(k); updateRange(k << 1, l, mid, x, y, w); updateRange(k << 1 | 1, mid + 1, r, x, y, w); segmentTree[k] = segmentTree[k << 1] + segmentTree[k << 1 | 1]; } void updatePoint(int k, int l, int r, int x) { if (l > x || x > r) { return; } if (l == r) { segmentTree[k].state ^= 1; if (segmentTree[k].state) { segmentTree[k].answer = segmentTree[k].d; } else { segmentTree[k].answer = INF; } return; } int mid = l + r >> 1; down(k); updatePoint(k << 1, l, mid, x); updatePoint(k << 1 | 1, mid + 1, r, x); segmentTree[k] = segmentTree[k << 1] + segmentTree[k << 1 | 1]; } ll get(int k, int l, int r, int x) { if (l == r) { return segmentTree[k].d; } int mid = l + r >> 1; down(k); if (x <= mid) { return get(k << 1, l, mid, x); } return get(k << 1 | 1, mid + 1, r, x); } }; IT tree[N]; int lowerBound(vector <int> &lst, int pos) { int l = 0, r = lst.size() - 1, mid, res = lst.size(); while (l <= r) { mid = l + r >> 1; if (in[lst[mid]] >= pos) { r = mid - 1; res = mid; } else { l = mid + 1; } } res++; return res; } int upperBound(vector <int> &lst, int pos) { int l = 0, r = lst.size() - 1, mid, res = lst.size(); while (l <= r) { mid = l + r >> 1; if (in[lst[mid]] > pos) { r = mid - 1; res = mid; } else { l = mid + 1; } } res++; return res; } ll query(int u) { ll ans = INF; int cur = u; while (cur <= n) { int p = lowerBound(tree[cur].lst, in[u]); ans = min(ans, tree[cur].get(1, 1, tree[cur].n, p) + tree[cur].segmentTree[1].answer); cur = parCd[cur]; } if (ans == INF) { ans = -1; } return ans; } void change(int u) { int cur = u; while (cur <= n) { int p = lowerBound(tree[cur].lst, in[u]); tree[cur].updatePoint(1, 1, tree[cur].n, p); cur = parCd[cur]; } } void path(int u, ll w) { int cur = u; while (cur <= n) { int L = lowerBound(tree[cur].lst, in[u]); int R = upperBound(tree[cur].lst, out[u]); R--; if (L <= R && R <= tree[cur].n) { if (checkSubtree(u, cur)) { if (L - 1 >= 1) { tree[cur].updateRange(1, 1, tree[cur].n, 1, L - 1, w); } if (R + 1 <= tree[cur].n) { tree[cur].updateRange(1, 1, tree[cur].n, R + 1, tree[cur].n, w); } } else { tree[cur].updateRange(1, 1, tree[cur].n, L, R, w); } } cur = parCd[cur]; } } void solve() { dfs(1); parCd[cd(1)] = n + 1; for (int i = 1; i <= n; i++) { u = i; while (u) { tree[u].lst.push_back(i); u = parCd[u]; } } for (int i = 1; i <= n; i++) { sort(tree[i].lst.begin(), tree[i].lst.end(), cmp); } for (int i = 1; i <= n; i++) { tree[i].n = tree[i].lst.size(); tree[i].root = i; node defVal; tree[i].segmentTree.resize((tree[i].n + 1) << 2, defVal); tree[i].build(1, 1, tree[i].n); } while (q--) { int type, u; cin >> type >> u; if (type == 1) { cout << query(u) << "\n"; } else if (type == 2) { change(u); } else { cin >> v >> w; int p = h[u] < h[v] ? v : u; path(p, w - val[p]); val[p] = w; } } } } int main() { ios_base :: sync_with_stdio(false); cin.tie(0); cout.tie(0); if (fopen(task".inp", "r")) { freopen(task".inp", "r", stdin); freopen(task".out", "w", stdout); } cin >> n >> q; for (int i = 1; i < n; i++) { cin >> u >> v >> w; adj[u].push_back({v, w}); adj[v].push_back({u, w}); } sub6 :: solve(); return 0; }

Compilation message (stderr)

Main.cpp: In function 'int main()':
Main.cpp:340:16: warning: ignoring return value of 'FILE* freopen(const char*, const char*, FILE*)' declared with attribute 'warn_unused_result' [-Wunused-result]
  340 |         freopen(task".inp", "r", stdin);
      |         ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
Main.cpp:341:16: warning: ignoring return value of 'FILE* freopen(const char*, const char*, FILE*)' declared with attribute 'warn_unused_result' [-Wunused-result]
  341 |         freopen(task".out", "w", stdout);
      |         ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~
#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...