Submission #1125657

#TimeUsernameProblemLanguageResultExecution timeMemory
1125657ShadowSharkGrapevine (NOI22_grapevine)C++20
100 / 100
1126 ms198400 KiB
#include <bits/stdc++.h> using namespace std; const int maxN = 1e5 + 5; const long long inf = 1e18; int n, q; /// Segment Treee struct node { long long dis, val, lazy; }; vector<node> st[maxN]; int statusGrape[maxN]; long long ngaos[maxN]; void down(int type, int id) { long long t = st[type][id].lazy; if (!t) return ; st[type][2 * id].lazy += t; st[type][2 * id].dis += t; st[type][2 * id].val += t; st[type][2 * id + 1].lazy += t; st[type][2 * id + 1].dis += t; st[type][2 * id + 1].val += t; st[type][id].lazy = 0; } void build(int type, int id, int l, int r) { if (l == r) { st[type][id].dis = ngaos[l]; st[type][id].val = inf; st[type][id].lazy = 0; return ; } int mid = (l + r) >> 1; build(type, 2 * id, l, mid); build(type, 2 * id + 1, mid + 1, r); st[type][id].val = min(st[type][2 * id].val, st[type][2 * id + 1].val); } void updateRange(int type, int id, int l, int r, int u, int v, long long val) { if (v < l || r < u) return ; if (u <= l && r <= v) { st[type][id].lazy += val; st[type][id].dis += val; st[type][id].val += val; return ; } int mid = (l + r) >> 1; down(type, id); updateRange(type, 2 * id, l, mid, u, v, val); updateRange(type, 2 * id + 1, mid + 1, r, u, v, val); st[type][id].val = min(st[type][2 * id].val, st[type][2 * id + 1].val); } void updateState(int type, int id, int l, int r, int pos, int grapeState) { if (l == r) { if (grapeState) st[type][id].val = st[type][id].dis; else st[type][id].val = inf; return ; } int mid = (l + r) >> 1; down(type, id); if (pos <= mid) updateState(type, 2 * id, l, mid, pos, grapeState); else updateState(type, 2 * id + 1, mid + 1, r, pos, grapeState); st[type][id].val = min(st[type][2 * id].val, st[type][2 * id + 1].val); } long long getDis(int type, int id, int l, int r, int pos) { if (l == r) return st[type][id].dis; int mid = (l + r) >> 1; down(type, id); if (pos <= mid) return getDis(type, 2 * id, l, mid, pos); return getDis(type, 2 * id + 1, mid + 1, r, pos); } /// Build Centroid vector<int> adj[maxN]; map<pair<int, int>, int> weight; int sz[maxN], par_cen[maxN]; void dfs_sz(int u, int pre) { sz[u] = 1; for (auto v: adj[u]) { if (v == pre || par_cen[v]) continue; dfs_sz(v, u); sz[u] += sz[v]; } } int getCentroid(int u, int pre, int m) { for (auto v: adj[u]) { if (v == pre || par_cen[v]) continue; if (sz[v] > m / 2) return getCentroid(v, u, m); } return u; } int timeDfs = 0; int layer[maxN], in[21][maxN], out[21][maxN], st_size[maxN]; long long depth[maxN]; void preDfs(int centroid, int u, int pre) { in[layer[centroid]][u] = ++timeDfs; ngaos[timeDfs] = depth[u]; for (auto v: adj[u]) { if (v == pre || par_cen[v]) continue; depth[v] = depth[u] + weight[{u, v}]; preDfs(centroid, v, u); } out[layer[centroid]][u] = timeDfs; } void build_centroid(int u, int pre) { dfs_sz(u, pre); int m = sz[u]; int centroid = getCentroid(u, pre, m); par_cen[centroid] = pre; st[centroid].resize(4 * m + 6); st_size[centroid] = m; layer[centroid] = (pre == -1 ? 1 : layer[par_cen[centroid]] + 1); timeDfs = 0; depth[centroid] = 0; preDfs(centroid, centroid, pre); build(centroid, 1, 1, st_size[centroid]); for (auto v: adj[centroid]) { if (par_cen[v]) continue; build_centroid(v, centroid); } } void debug_dis() { cout << "Debug_dis\n"; for (int i = 1; i <= n; i++) { for (int j = 1; j <= st_size[i]; j++) cout << getDis(i, 1, 1, st_size[i], j) << ' '; cout << '\n'; } cout << '\n'; } int similar(int u, int v) { if (layer[u] < layer[v]) swap(u, v); while (layer[u] > layer[v]) u = par_cen[u]; while (u != v) { u = par_cen[u]; v = par_cen[v]; } return u; } int main() { ios::sync_with_stdio(0); cin.tie(0); cout.tie(0); //freopen("grapevine.inp", "r", stdin); //freopen("grapevine.ans", "w", stdout); cin >> n >> q; for (int i = 1; i < n; i++) { int u, v, w; cin >> u >> v >> w; adj[u].push_back(v); adj[v].push_back(u); weight[{u, v}] = weight[{v, u}] = w; } build_centroid(1, -1); while (q--) { int type, u; cin >> type >> u; if (type == 1) { long long res = inf; int x = u; while (x != -1) { res = min(res, st[x][1].val + getDis(x, 1, 1, st_size[x], in[layer[x]][u])); x = par_cen[x]; } if (res > 1e14) cout << -1 << '\n'; else cout << res << '\n'; } else if (type == 2) { statusGrape[u] ^= 1; int x = u; while (x != -1) { updateState(x, 1, 1, st_size[x], in[layer[x]][u], statusGrape[u]); x = par_cen[x]; } } else { int v, w; cin >> v >> w; int prev_weight = weight[{u, v}]; int x = similar(u, v); while (x != -1) { int l, r; if (in[layer[x]][u] < in[layer[x]][v]) { l = in[layer[x]][v]; r = out[layer[x]][v]; } else { l = in[layer[x]][u]; r = out[layer[x]][u]; } updateRange(x, 1, 1, st_size[x], l, r, w - prev_weight); x = par_cen[x]; } weight[{u, v}] = weight[{v, u}] = w; } } 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...