This submission is migrated from previous version of oj.uz, which used different machine for grading. This submission may have different result if resubmitted.
// Author: Ivan Teo
// Created: Sun Jun 23 11:05:28 2024
// #pragma GCC optimize("Ofast")
#define TASKNAME "1192B"
#include <bits/stdc++.h>
using namespace std;
#define fore(i, a, b) for (int i = (a); i <= (b); i++)
#define int long long
using vi = vector<int>;
using ii = pair<int, int>;
#define pb emplace_back
#define fi first
#define se second
#define sz(v) ((int)v.size())
#define all(v) v.begin() + 1, v.end()
#define alll(v) v.begin(), v.end()
#define db(x) cerr << "[" << #x << " = " << x << "]"
#define el cerr << "\n=========================================\n"
mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());
int Rand(int l, int r)
{
assert(l <= r);
return uniform_int_distribution<int> (l, r)(rng);
}
#define idl (id << 1)
#define idr (id << 1 | 1)
struct SegmentTree
{
int n;
vector<ii> st;
vi lz;
vi a;
SegmentTree() {}
SegmentTree(int n, vi a): n(n), st(4 * n + 5), lz(4 * n + 5), a(a)
{
build(1, 1, n);
}
void add(int id, int v)
{
st[id].fi += v;
lz[id] += v;
}
void push(int id)
{
add(idl, lz[id]);
add(idr, lz[id]);
lz[id] = 0;
}
void build(int id, int l, int r)
{
if (l > r) return ;
if (l == r) return (void)(st[id] = {a[l], l});
int m = (l + r) >> 1;
build(idl, l, m);
build(idr, m + 1, r);
st[id] = max(st[idl], st[idr]);
}
void add(int id, int l, int r, int tl, int tr, int v)
{
if (l > r || l > tr || r < tl) return ;
if (l >= tl && r <= tr) return (void)(add(id, v));
push(id);
int m = (l + r) >> 1;
add(idl, l, m, tl, tr, v);
add(idr, m + 1, r, tl, tr, v);
st[id] = max(st[idl], st[idr]);
}
int get(int id, int l, int r, int tl, int tr)
{
if (l > r || l > tr || r < tl) return 0;
if (l >= tl && r <= tr) return st[id].fi;
push(id);
int m = (l + r) >> 1;
return max(get(idl, l, m, tl, tr), get(idr, m + 1, r, tl, tr));
}
void add(int l, int r, int v)
{
add(1, 1, n, l, r, v);
}
int get(int l, int r)
{
return get(1, 1, n, l, r);
}
ii get()
{
return st[1];
}
};
using iii = tuple<int, int, int>;
struct Tree
{
vector<iii> e;
vector<vector<ii>> g;
vi dep, branch, in, out, pw, l, inv;
SegmentTree st;
int n, root, timer = 0, diam = 0;
Tree() {}
void init(vector<iii> &e, int _root)
{
root = _root;
for (auto &[u, v, w] : e) l.pb(u), l.pb(v);
sort(alll(l));
l.erase(unique(alll(l)), l.end());
n = sz(l);
g = vector<vector<ii>>(n + 1);
inv = pw = in = out = dep = branch = vi(n + 1);
for (auto &[u, v, w] : e)
{
u = lower_bound(alll(l), u) - l.begin() + 1;
v = lower_bound(alll(l), v) - l.begin() + 1;
g[u].pb(v, w);
g[v].pb(u, w);
}
root = lower_bound(alll(l), root) - l.begin() + 1;
dfs(root, 0);
st = SegmentTree(n, dep);
get();
}
void dfs(int u, int p)
{
in[u] = ++timer;
inv[timer] = u;
if (p == root) branch[u] = u;
else if (u != root) branch[u] = branch[p];
for (auto &[v, w] : g[u]) if (v != p)
{
dep[timer + 1] = dep[in[u]] + w;
pw[v] = w;
dfs(v, u);
}
out[u] = timer;
}
void upd(int u, int v, int w)
{
u = lower_bound(alll(l), u) - l.begin() + 1;
v = lower_bound(alll(l), v) - l.begin() + 1;
if (in[u] > in[v]) swap(u, v);
st.add(in[v], out[v], w - pw[v]);
pw[v] = w;
get();
}
void get()
{
auto [dist, u] = st.get();
u = inv[u];
dist += max(st.get(1, in[branch[u]] - 1), st.get(out[branch[u]] + 1, n));
diam = dist;
}
};
signed main()
{
cin.tie(0)->sync_with_stdio(0);
int n, q, W;
cin >> n >> q >> W;
vector<vector<iii>> g(n + 1);
vector<ii> edge;
vector<vi> group(n - 1);
fore(i, 1, n - 1)
{
int u, v, w;
cin >> u >> v >> w;
g[u].pb(v, w, i - 1);
g[v].pb(u, w, i - 1);
edge.pb(u, v);
}
vi sz = vi(n + 1), del(n + 1);
function<int(int, int, int)> centroid = [&](int u, int p, int n)
{
for (auto &[v, w, id] : g[u]) if (!del[v] && v != p)
if (sz[v] * 2 > n) return centroid(v, u, n);
return u;
};
function<void(int, int)> dfs = [&](int u, int p)
{
sz[u] = 1;
for (auto &[v, w, id] : g[u]) if (!del[v] && v != p)
dfs(v, u), sz[u] += sz[v];
};
vector<iii> e;
vector<Tree> jungle;
function<void(int, int)> add = [&](int u, int p)
{
for (auto &[v, w, id] : g[u]) if (!del[v] && v != p)
add(v, u), e.pb(u, v, w), group[id].pb(sz(jungle));
};
function<void(int)> go = [&](int u)
{
dfs(u, 0);
int root = centroid(u, 0, sz[u]);
del[root] = 1;
e.clear();
add(root, 0);
if (sz(e)) jungle.pb(), jungle.back().init(e, root);
for (auto &[v, w, id] : g[root]) if (!del[v])
go(v);
};
go(1);
multiset<int> ms;
int last = 0;
fore(i, 0, sz(jungle) - 1) ms.insert(jungle[i].diam);
while (q--)
{
int id, w;
cin >> id >> w;
id = (id + last) % (n - 1);
w = (w + last) % W;
int ans = 0;
for (auto i : group[id])
{
ms.erase(ms.find(jungle[i].diam));
jungle[i].upd(edge[id].fi, edge[id].se, w);
ms.insert(jungle[i].diam);
}
ans = *ms.rbegin();
cout << ans << '\n';
last = ans;
}
return 0;
}
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |