(UPD: 2024-12-04 14:48 UTC) Judge is not working due to Cloudflare incident. (URL) We can do nothing about it, sorry. After the incident is resolved, we will grade all submissions.

Submission #373120

#TimeUsernameProblemLanguageResultExecution timeMemory
373120ACmachineDynamic Diameter (CEOI19_diameter)C++17
100 / 100
4588 ms134232 KiB
#include <bits/stdc++.h> using namespace std; #include <ext/pb_ds/assoc_container.hpp> #include <ext/pb_ds/tree_policy.hpp> using namespace __gnu_pbds; template<typename T> using ordered_set = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>; template<typename T, typename U> using ordered_map = tree<T, U, less<T>, rb_tree_tag, tree_order_statistics_node_update>; typedef long long ll; typedef long double ld; typedef pair<int,int> pii; typedef pair<ll,ll> pll; typedef vector<int> vi; typedef vector<ll> vll; #define FOR(i,j,k,in) for(int i=(j); i < (k);i+=in) #define FORD(i,j,k,in) for(int i=(j); i >=(k);i-=in) #define REP(i,b) FOR(i,0,b,1) #define REPD(i,b) FORD(i,b,0,1) #define pb push_back #define mp make_pair #define ff first #define ss second #define all(x) begin(x), end(x) #define MANY_TESTS int tcase; cin >> tcase; while(tcase--) const double EPS = 1e-9; const int MOD = 1e9+7; const ll INFF = 1e18; const int INF = 1e9; const ld PI = acos((ld)-1); const vi dy = {1, 0, -1, 0, -1, 1, 1, -1}; const vi dx = {0, 1, 0, -1, -1, 1, -1, 1}; void DBG(){cout << "]" << endl;} template<typename T, typename ...U> void DBG(const T& head, const U... args){ cout << head << "; "; DBG(args...); } #define dbg(...) cout << "Line(" << __LINE__ << ") -> [" << #__VA_ARGS__ << "]: [", DBG(__VA_ARGS__); #define chk() cout << "Check at line(" << __LINE__ << ") hit." << endl; template<class T, unsigned int U> ostream& operator<<(ostream& out, const array<T, U> &v){out << "["; REP(i, U) out << v[i] << ", "; out << "]"; return out;} template <class T, class U> ostream& operator<<(ostream& out, const pair<T, U> &par) {out << "[" << par.first << ";" << par.second << "]"; return out;} template <class T> ostream& operator<<(ostream& out, const set<T> &cont) { out << "{"; for( const auto &x:cont) out << x << ", "; out << "}"; return out; } template <class T, class U> ostream& operator<<(ostream& out, const map<T, U> &cont) {out << "{"; for( const auto &x:cont) out << x << ", "; out << "}"; return out; } template<class T> ostream& operator<<(ostream& out, const vector<T> &v){ out << "["; REP(i, v.size()) out << v[i] << ", "; out << "]"; return out;} template<class T> istream& operator>>(istream& in, vector<T> &v){ for(auto &x : v) in >> x; return in; } struct node{ ll ans = 0, lazy = 0; void apply(int l, int r, ll val){ ans += val; lazy += val; } }; struct segtree{ node comb(node const &a, node const &b){ node res; res.ans = max(a.ans, b.ans); return res; } void push(int l, int r, int v){ if(tree[v].lazy == 0) return; tree[v<<1].lazy += tree[v].lazy; tree[v<<1|1].lazy += tree[v].lazy; tree[v<<1].ans += tree[v].lazy; tree[v<<1|1].ans += tree[v].lazy; tree[v].lazy = 0; } int sz; vector<node> tree; segtree(){} segtree(int _sz){ // tree is resized to default values set in node sz = 1; while(sz < _sz) sz<<=1; tree.resize(2*sz); } void build(vector<node> &init){ for(int i = 0; i < sz; ++i) if(i < init.size()) tree[i+sz] = init[i]; for(int i = sz-1; i > 0; --i) tree[i] = comb(tree[i<<1], tree[i<<1|1]); } node query(int l, int r){return query0(l, r, 0, sz, 1);} node query0(int l, int r, int beg, int end, int v){ if(beg >= l && end <= r) return tree[v]; push(beg, end, v); int mid = (beg + end) >> 1; node res; if(beg >= r || mid <= l) res = query0(l, r, mid, end, v<<1|1); //[beg, mid] else if(mid >= r || end <= l) res = query0(l, r, beg, mid, v<<1); else res = comb(query0(l, r, beg, mid, v<<1), query0(l, r, mid, end, v<<1|1)); return res; } template<typename... T> void upd(int l, int r, T ...args){upd0(l, r, 0, sz, 1, args...);} template<typename... T> void upd0(int l, int r, int beg, int end, int v, T ...args){ if(beg >= r || end <= l) return; if(beg >= l && end <= r){ tree[v].apply(beg, end, args...); return; } push(beg, end, v); int mid = (beg + end) >> 1; upd0(l, r, beg, mid, v<<1, args...); upd0(l, r, mid, end, v<<1|1, args...); tree[v] = comb(tree[v<<1], tree[v<<1|1]); } }; int main(){ ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL); int n, q; ll w; cin >> n >> q; cin >> w; vector<vector<array<ll, 2>>> g(n); vector<array<ll, 3>> edges(n - 1); // centroids for full, but too hard to impl, impl at the end if time REP(i, n - 1){ ll a, b, c; cin >> a >> b >> c; a--; b--; g[a].pb({b, i}); g[b].pb({a, i}); edges[i] = {a, b, c}; } auto solve12 = [&](){ int diam1, diam2; vector<ll> dist(n, 0); function<void(int, int)> dfs = [&](int v, int p){ for(auto x : g[v]){ if(x[0] == p) continue; ll weight = edges[x[1]][2]; dist[x[0]] = dist[v] + weight; dfs(x[0], v); } }; dfs(0, -1); diam1 = max_element(all(dist)) - dist.begin(); dist[diam1] = 0; dfs(diam1, -1); diam2 = max_element(all(dist)) - dist.begin(); ll last = 0; REP(i, q){ ll d, e; cin >> d >> e; d = (d + last) % (n - 1); e = (e + last) % w; edges[d][2] = e; dist[diam1] = 0; dfs(diam1, -1); int nxt_diam2 = max_element(all(dist)) - dist.begin(); ll nxt_diamw2 = *max_element(all(dist)); dist[diam2] = 0; dfs(diam2, -1); int nxt_diam1 = max_element(all(dist)) - dist.begin(); ll nxt_diamw1 = *max_element(all(dist)); if(nxt_diamw1 > nxt_diamw2){ last = nxt_diamw1; diam1 = nxt_diam1; } else{ last = nxt_diamw2; diam2 = nxt_diam2; } cout << last << "\n"; } }; //solve12(); auto solve = [&](){ vector<multiset<ll>> depths(n); // for each centroid multiset<ll> answers; vector<int> par(n, -1); // parent in centroid tree vector<int> lev(n, 0); // level of centroid const int mxlv = 19; vector<vector<int>> in(mxlv, vector<int>(n, -1)); vector<vector<int>> out(mxlv, vector<int>(n, -1)); vector<vector<int>> sub_root(mxlv, vector<int>(n, -1)); vector<segtree> segtrees(n); vector<bool> dead(n, false); vector<int> sub(n, 0); auto compute_ans = [](multiset<ll> &se){ multiset<ll> :: reverse_iterator it = se.rbegin(); if(se.size() == 0) return 0ll; ll res = *it; if(se.size() > 1){ it++; res += *it; } return res; }; function<void(int, int)> getsub = [&](int v, int p){ sub[v] = 1; for(auto x : g[v]){ if(x[0] == p) continue; if(dead[x[0]]) continue; getsub(x[0], v); sub[v] += sub[x[0]]; } }; function<int(int, int, int)> get_centroid = [&](int v, int p, int total_size){ int heavy_child = -1; for(auto x : g[v]){ if(x[0] == p || dead[x[0]]) continue; if(sub[x[0]] > total_size / 2) heavy_child = x[0]; } if(heavy_child == -1) return v; else return get_centroid(heavy_child, v, total_size); }; function<void(int, int)> decompose = [&](int v, int p){ // find centroid of this subtree getsub(v, -1); int centroid = get_centroid(v, -1, sub[v]); par[centroid] = p; // par in centroid tree if(p != -1) lev[centroid] = lev[p] + 1; int t = 0; segtrees[centroid] = segtree(sub[v]); vector<node> init(sub[v]); int level = lev[centroid]; function<void(int, int, ll, int)> dfs = [&](int v, int p, ll depth, int subrootnum){ in[level][v] = t; init[t].ans = depth; sub_root[level][v] = subrootnum; t++; for(auto x : g[v]){ if(x[0] == p || dead[x[0]]) continue; ll weight = edges[x[1]][2]; dfs(x[0], v, depth + weight, subrootnum); } out[level][v] = t; }; for(auto x : g[centroid]){ if(dead[x[0]]) continue; ll weight = edges[x[1]][2]; dfs(x[0], centroid, weight, x[0]); } segtrees[centroid].build(init); for(auto x : g[centroid]){ if(dead[x[0]]) continue; depths[centroid].insert(segtrees[centroid].query(in[level][x[0]], out[level][x[0]]).ans); } answers.insert(compute_ans(depths[centroid])); dead[centroid] = true; for(auto x : g[centroid]){ if(dead[x[0]]) continue; decompose(x[0], centroid); } }; decompose(0, -1); ll last = 0; REP(i, q){ ll d, e; cin >> d >> e; d = (d + last) % (n - 1); e = (e + last) % w; auto edge = edges[d]; int frs; // prvy centroid ktoreho sa to dotkne if(lev[edge[0]] < lev[edge[1]]) frs = edge[0]; else frs = edge[1]; while(frs != -1){ answers.erase(answers.find(compute_ans(depths[frs]))); int centroid_lev = lev[frs]; int desc; if(in[centroid_lev][edge[0]] > in[centroid_lev][edge[1]]) desc = edge[0]; else desc = edge[1]; ll delta = e - edge[2]; int root = sub_root[centroid_lev][desc]; depths[frs].erase(depths[frs].find(segtrees[frs].query(in[centroid_lev][root], out[centroid_lev][root]).ans)); segtrees[frs].upd(in[centroid_lev][desc], out[centroid_lev][desc], delta); depths[frs].insert(segtrees[frs].query(in[centroid_lev][root], out[centroid_lev][root]).ans); answers.insert(compute_ans(depths[frs])); frs = par[frs]; } edges[d][2] = e; last = *answers.rbegin(); cout << last << "\n"; } }; solve(); return 0; }

Compilation message (stderr)

diameter.cpp: In member function 'void segtree::build(std::vector<node>&)':
diameter.cpp:87:18: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<node>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
   87 |             if(i < init.size())
      |                ~~^~~~~~~~~~~~~
diameter.cpp: In function 'int main()':
diameter.cpp:139:10: warning: variable 'solve12' set but not used [-Wunused-but-set-variable]
  139 |     auto solve12 = [&](){
      |          ^~~~~~~
#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...