제출 #1170251

#제출 시각아이디문제언어결과실행 시간메모리
1170251nathan4690Grapevine (NOI22_grapevine)C++20
100 / 100
908 ms168032 KiB
// Cay nho - GRAPE // NOI Singapore 2022 Task 4: Grapevine #include <bits/stdc++.h> #define ll long long #define ld long double #define f1(i,n) for(int i=1;i<=n;i++) #define __file_name "" using namespace std; const ll maxn=1e5+5, inf=1e16; struct Lazy{ long long data = 0; Lazy(){}; Lazy(long long data): data(data){}; Lazy operator+(const Lazy &rhs) const{ // Push a lazy down return Lazy(data + rhs.data); } }; struct Value{ long long data = 1e18; Value(){}; Value(long long data): data(data){}; Value operator+(const Value &rhs) const{ // Merge two nodes return Value(min(data, rhs.data)); } Value operator+(const Lazy &rhs) const{ // Apply lazy to node return Value(data + rhs.data); } }; template<class T, class U> struct SegmentTree{ int n; vector<T> st; vector<U> lazy; SegmentTree(){}; SegmentTree(int n): n(n), st(4*n+1), lazy(4*n+1){}; inline void down(int idx){ st[idx*2] = st[idx*2] + lazy[idx]; lazy[idx*2] = lazy[idx*2] + lazy[idx]; st[idx*2+1] = st[idx*2+1] + lazy[idx]; lazy[idx*2+1] = lazy[idx*2+1] + lazy[idx]; lazy[idx] = U(); } void _upd1(int idx, int l, int r, int i, const T &v){ if(i < l || r < i) return; if(l == r){ st[idx] = v; return; } down(idx); int mid = (l + r) / 2; _upd1(idx*2, l, mid, i, v); _upd1(idx*2+1, mid+1, r, i, v); st[idx] = st[idx*2] + st[idx*2+1]; } inline void updatePoint(int position, const T &value){ _upd1(1,1,n,position,value); } void _upd2(int idx, int l, int r, int u, int v, const U &w){ if(v < l || r < u) return; if(u <= l && r <= v){ st[idx] = st[idx] + w; lazy[idx] = lazy[idx] + w; return; } down(idx); int mid = (l + r) / 2; _upd2(idx*2, l, mid, u, v, w); _upd2(idx*2+1, mid+1, r, u, v, w); st[idx] = st[idx*2] + st[idx*2+1]; } inline void updateRange(int left_, int right_, const U &value){ _upd2(1,1,n,left_, right_, value); } T _get(int idx, int l, int r, int u, int v){ if(v < l || r < u) return T(); if(u <= l && r <= v) return st[idx]; down(idx); int mid = (l + r) / 2; return _get(idx*2, l, mid, u, v) + _get(idx*2+1, mid+1, r, u, v); } inline T getRange(int left_, int right_){ return _get(1,1,n,left_, right_); } }; #define SegTree SegmentTree<Value,Lazy> int n, q, wei[maxn]; vector<pair<int,int>> G[maxn]; map<int, int> edgeID[maxn]; bool haveGrape[maxn]; int sz[maxn], parc[maxn], depc[maxn]; bool del[maxn]; void dfs_sz(int u, int p){ sz[u] = 1; for(pair<int,int> e: G[u]){ int c = e.first; if(c != p && !del[c]){ dfs_sz(c, u); sz[u] += sz[c]; } } } int find_centroid(int u, int p, int N){ for(pair<int,int> e: G[u]){ int c = e.first; if(c != p && !del[c] && sz[c] > N / 2){ return find_centroid(c, u, N); } } return u; } vector<int> sp[maxn], ep[maxn], nodes[maxn]; int timer; SegTree st[maxn]; void build_euler(int u, int p, int root, ll cdep){ int idx = nodes[root].size(); nodes[root].push_back(u); st[root].updatePoint(timer, cdep + inf); sp[root].push_back(timer++); ep[root].push_back(0); for(pair<int,int> e: G[u]){ int c = e.first, w = wei[e.second]; if(c != p && !del[c]){ build_euler(c, u, root, cdep + w); } } ep[root][idx] = timer - 1; } void build_cen(int u, int p = 0, int dd = 0){ dfs_sz(u, 0); int root = find_centroid(u, 0, sz[u]); parc[root] = p; depc[root] = dd; st[root] = SegTree(sz[u]); timer = 1; build_euler(root, 0, root, 0); vector<pair<int,int>> tmpnode; for(int i=0;i<nodes[root].size();i++){ tmpnode.push_back({nodes[root][i], i}); } sort(tmpnode.begin(), tmpnode.end()); vector<int> tmpv; nodes[root].clear(); for(pair<int,int> item: tmpnode){ nodes[root].push_back(item.first); tmpv.push_back(sp[root][item.second]); } swap(sp[root], tmpv); tmpv.clear(); for(pair<int,int> item: tmpnode){ tmpv.push_back(ep[root][item.second]); } swap(ep[root], tmpv); del[root] = true; for(pair<int,int> e: G[root]){ int c = e.first; if(!del[c]) { build_cen(c, root, depc[root] + 1); } } } //int par[17][maxn], udep[maxn]; //ll depth[maxn]; //void binlift(int u, int p){ // par[0][u] = p; // for(int i=1;i<17;i++) par[i][u] = par[i-1][par[i-1][u]]; // for(pair<int,int> e: G[u]){ // int c = e.first, w = wei[e.second]; // if(c != p){ // depth[c] = depth[u] + w; // udep[c] = udep[u] + 1; // binlift(c, u); // } // } //} // //int LCA(int u, int v){ // if(udep[u] < udep[v]) swap(u, v); // int l = udep[u] - udep[v]; // for(int i=0;i<17;i++){ // if(l >> i & 1) u = par[i][u]; // } // if(u == v) return u; // for(int i=16;i>=0;i--){ // if(par[i][u] != par[i][v]){ // u = par[i][u]; // v = par[i][v]; // } // } // return par[0][u]; //} ll getDist(int root, int u){ int idx = lower_bound(nodes[root].begin(), nodes[root].end(), u) - nodes[root].begin(); ll res = st[root].getRange(sp[root][idx], sp[root][idx]).data; if(!haveGrape[u]) res -= inf; return res; } int main(){ ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0); if(fopen(__file_name ".inp", "r")){ freopen(__file_name ".inp", "r", stdin); freopen(__file_name ".out", "w", stdout); } // code here cin >> n >> q; f1(i,n-1){ int u, v, w; cin >> u >> v >> w; wei[i] = w; G[u].push_back({v, i}); G[v].push_back({u, i}); edgeID[u][v] = edgeID[v][u] = i; } // binlift(1, 0); build_cen(1); while(q--){ int tp; cin >> tp; if(tp == 1){ int u; cin >> u; ll ans = inf; int v = u; while(v != 0){ // cout << v << " -> " << u << ' ' << ans << ' ' << getDist(v, u) << ' ' << st[v].st[1].data << '\n'; ans = min(ans, getDist(v, u) + st[v].st[1].data); v = parc[v]; } cout << (ans >= 1e15 ? -1LL : ans) << '\n'; }else if(tp == 2){ int u; cin >> u; int v = u; while(v != 0){ int idx = lower_bound(nodes[v].begin(), nodes[v].end(), u) - nodes[v].begin(); ll newVal = (haveGrape[u] ? inf : -inf); st[v].updateRange(sp[v][idx], sp[v][idx], newVal); // cout << "! " << v << " => " << u << ' ' << parc[v] << ' ' << newVal << '\n'; v = parc[v]; } haveGrape[u] = !haveGrape[u]; }else{ int u, v, w; cin >> u >> v >> w; int eidx = edgeID[u][v]; ll diff = w - wei[eidx]; wei[eidx] = w; if(depc[u] > depc[v]) swap(u, v); // move from u up int root = u; while(root != 0){ int uidx = lower_bound(nodes[root].begin(), nodes[root].end(), u) - nodes[root].begin(); int vidx = lower_bound(nodes[root].begin(), nodes[root].end(), v) - nodes[root].begin(); if(sp[root][vidx] <= sp[root][uidx] && ep[root][uidx] <= ep[root][vidx]){ swap(uidx, vidx); } // u is parent of v in root st[root].updateRange(sp[root][vidx], ep[root][vidx], diff); root = parc[root]; } } } return 0; }

컴파일 시 표준 에러 (stderr) 메시지

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