Submission #1287411

#TimeUsernameProblemLanguageResultExecution timeMemory
1287411red_soulsGrapevine (NOI22_grapevine)C++17
53 / 100
1106 ms234096 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{ long long d, answer; bool state; Node(){ d = answer = INF; state = false; } Node operator + (const Node &rhs) const { if(answer < rhs.answer) return *this; return rhs; } }; struct Interval{ int root, numNode; vector<int> node; vector<Node> it; vector<long long> lz; inline void reSize(int n = 0){ it.resize(n << 2, Node()); lz.resize(n << 2, 0); numNode = n; } inline void init(int id, int l, int r){ if(l == r){ it[id].d = d[node[l - 1]] + d[root] - 2 * d[lca(node[l - 1], root)]; return; } int mid = l + r >> 1; init(id << 1, l, mid); init(id << 1 | 1, mid + 1, r); } inline void push(int id){ long long &z = lz[id]; if(z == 0) return; for (int v = id << 1; v <= (id << 1 | 1); v++) { it[v].d += z; it[v].answer += z; it[v].answer = min(it[v].answer, INF); lz[v] += z; } z = 0; } inline void modifyChange(int id, int l, int r, int p){ if(l == r){ it[id].state ^= 1; if(it[id].state) it[id].answer = it[id].d; else { it[id].answer = INF; } return; } int mid = l + r >> 1; push(id); if(p <= mid)modifyChange(id << 1, l, mid, p); else modifyChange(id << 1 | 1, mid + 1, r, p); it[id] = it[id << 1] + it[id << 1 | 1]; } inline void modifyRange(int id, int l,int r, int u, int v, int w){ if(l > v || r < u) return; if(l >= u && r <= v){ it[id].d += w; it[id].answer += w; it[id].answer = min(it[id].answer, INF); lz[id] += w; return; } int mid = l + r >> 1; push(id); modifyRange(id << 1, l, mid, u, v, w); modifyRange(id << 1 | 1, mid + 1, r, u, v, w); it[id] = it[id << 1] + it[id << 1 | 1]; } inline long long getDepth(int id, int l, int r, int p){ if(l == r) return it[id].d; int mid = l + r >> 1; push(id); if(p <= mid) return getDepth(id << 1, l, mid, p); else return getDepth(id << 1 | 1, mid + 1, r, p); } }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) { int p = lowerBound(tree[cur].node, in[u]); ans = min(ans, tree[cur].getDepth(1, 1, tree[cur].numNode, p) + tree[cur].it[1].answer); cur = parCd[cur]; } if (ans == INF) { ans = -1; } return ans; } void change(int u) { int cur = u; while (cur) { int p = lowerBound(tree[cur].node, in[u]); tree[cur].modifyChange(1, 1, tree[cur].numNode, p); cur = parCd[cur]; } } void path(int u, ll w) { int cur = u; while (cur) { int L = lowerBound(tree[cur].node, in[u]); int R = upperBound(tree[cur].node, out[u]); R--; if (L <= R && R <= tree[cur].numNode) { if (checkSubtree(u, cur)) { if (L - 1 >= 1) { tree[cur].modifyRange(1, 1, tree[cur].numNode, 1, L - 1, w); } if (R + 1 <= tree[cur].numNode) { tree[cur].modifyRange(1, 1, tree[cur].numNode, R + 1, tree[cur].numNode, w); } } else { tree[cur].modifyRange(1, 1, tree[cur].numNode, L, R, w); } } cur = parCd[cur]; } } void solve() { dfs(1); cd(1); for (int i = 1; i <= n; i++) { u = i; while (u) { tree[u].node.push_back(i); u = parCd[u]; } } for (int i = 1; i <= n; i++) { sort(tree[i].node.begin(), tree[i].node.end(), cmp); } for (int i = 1; i <= n; i++) { tree[i].reSize(tree[i].node.size()); tree[i].root = i; tree[i].init(1, 1, tree[i].numNode); } 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:312:16: warning: ignoring return value of 'FILE* freopen(const char*, const char*, FILE*)' declared with attribute 'warn_unused_result' [-Wunused-result]
  312 |         freopen(task".inp", "r", stdin);
      |         ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
Main.cpp:313:16: warning: ignoring return value of 'FILE* freopen(const char*, const char*, FILE*)' declared with attribute 'warn_unused_result' [-Wunused-result]
  313 |         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...