This submission is migrated from previous version of oj.uz, which used different machine for grading. This submission may have different result if resubmitted.
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define pii pair<int, ll>
#define pli pair<ll, ll>
#define fi first
#define se second
const int MX = 1e5 + 10;
const int LG = 17;
const ll INF = 1e18 + 7;
int N, Q; ll W;
vector<int> adj[MX];
vector<pair<pli, ll>> edges;
int sz[MX], dead[MX];
void dfs(int u, int v){
sz[u] = 1;
for(int nx : adj[u]){
if(nx == v || dead[nx]) continue;
dfs(nx, u);
sz[u] += sz[nx];
}
}
int cent = -1, ccsize = 0;
void dfc(int u, int v){
for(int nx : adj[u]){
if(nx == v || dead[nx]) continue;
dfc(nx, u);
}
if(cent == -1 && sz[u] >= (ccsize + 1) / 2) cent = u;
}
int layer = 0, tim[LG], in[MX][LG], fn[MX][LG], root[MX][LG], par[MX][LG], lnum[MX];
// Centroid Decomposition Layer
// Euler Tour (in, out) for each layer
// Root (Centroid) for each layer
// Parent (if Centroid is root) for each layer
void init(int u, int v){
root[u][layer] = cent;
par[u][layer] = v;
in[u][layer] = ++tim[layer];
for(int nx : adj[u]){
if(nx == v || dead[nx]) continue;
init(nx, u);
}
fn[u][layer] = tim[layer];
}
#define psi pair<int, int>
vector<psi> adt[MX];
void findCentroid(int u){
dfs(u, 0);
ccsize = sz[u], cent = -1;
dfc(u, 0);
// cout << "Centroid is " << cent << '\n';
{
init(cent, 0); lnum[cent] = layer;
for(int nx : adj[cent])
if(!dead[nx]) adt[cent].push_back({in[nx][layer], nx});
sort(adt[cent].begin(), adt[cent].end());
}
{
dead[cent] = true;
for(int nx : adj[cent]){
if(dead[nx]) continue;
layer++; findCentroid(nx); layer--;
}
}
}
struct itseg{
ll st[MX << 1];
void upd(int p, ll v){
for(p += MX, st[p] = v, p >>= 1; p > 0; p >>= 1) st[p] = max(st[p << 1], st[p << 1|1]);
}
ll que(int l, int r){
ll res = 0;
for(l += MX, r += MX + 1; l < r; l >>= 1, r >>= 1){
if(l & 1) res = max(res, st[l++]);
if(r & 1) res = max(res, st[--r]);
}
return res;
}
} superseg;
struct segtree{
ll st[MX << 2], lz[MX << 2];
void prop(int id, int l, int r){
if(lz[id] == 0) return;
st[id] += lz[id];
if(l != r){
lz[id << 1] += lz[id];
lz[id << 1|1] += lz[id];
}
lz[id] = 0;
}
void upd(int id, int l, int r, int from, int to, ll v){
prop(id, l, r);
if(r < from || l > to) return;
if(from <= l && r <= to){
lz[id] += v;
prop(id, l, r);
}else{
int mid = l + r >> 1;
upd(id << 1, l, mid, from, to, v);
upd(id << 1|1, mid + 1, r, from, to, v);
st[id] = max(st[id << 1], st[id << 1|1]);
}
}
ll query(int id, int l, int r, int from, int to){
prop(id, l, r);
if(r < from || l > to) return -INF;
if(from <= l && r <= to){
return st[id];
}else{
int mid = l + r >> 1;
return max(
query(id << 1, l, mid, from, to),
query(id << 1|1, mid + 1, r, from, to)
);
}
}
} seg[LG];
set<pli> dep[MX];
// vector<int> adt[MX];
int main(){
ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
cin >> N >> Q >> W;
for(int i = 1; i < N; i++){
int u, v; ll w; cin >> u >> v >> w;
adj[u].push_back(v);
adj[v].push_back(u);
edges.push_back({{u, v}, w});
}
// cout << "find Centroid" << '\n';
findCentroid(1);
for(auto x : edges){
int u = x.fi.fi, v = x.fi.se;
ll w = x.se;
for(int j = 0; j < LG; j++){
if(root[u][j] != root[v][j]) break;
if(in[u][j] < in[v][j]) seg[j].upd(1, 1, N, in[v][j], fn[v][j], w);
else seg[j].upd(1, 1, N, in[u][j], fn[u][j], w);
}
}
for(int i = 1; i <= N; i++){
int lyr = lnum[i];
for(psi& nx : adt[i]) dep[i].insert({seg[lyr].query(1, 1, N, in[nx.se][lyr], fn[nx.se][lyr]), in[nx.se][lyr]});
{
ll ans = 0;
set<pli>::iterator it = dep[i].end();
if(it != dep[i].begin()){
it--;
ans += (*it).fi;
}
if(it != dep[i].begin()){
it--;
ans += (*it).fi;
}
superseg.upd(i, ans);
// cout << "answer for centroid " << i << " is " << ans << '\n';
}
}
// cout << "update depths" << '\n';
ll last = 0;
for(int i = 0; i < Q; i++){
int idx; ll nw; cin >> idx >> nw;
idx = (int)((last + idx) % (N - 1));
nw = (last + nw) % W;
int u = edges[idx].fi.fi, v = edges[idx].fi.se;
ll df = nw - edges[idx].se;
// cout << "update edge " << u << " " << v << '\n';
for(int j = 0; j < LG; j++){
if(root[u][j] != root[v][j]) break;
int rt = root[u][j], pnd = -1;
// cout << "at layer " << j << " " << root[u][j] << '\n';
if(in[u][j] > in[v][j]){
int uid = lower_bound(adt[rt].begin(), adt[rt].end(), make_pair(in[u][j] + 1, -1)) - adt[rt].begin();
pnd = adt[rt][uid - 1].se;
}else{
int uid = lower_bound(adt[rt].begin(), adt[rt].end(), make_pair(in[v][j] + 1, -1)) - adt[rt].begin();
pnd = adt[rt][uid - 1].se;
}
dep[rt].erase(make_pair(seg[j].query(1, 1, N, in[pnd][j], fn[pnd][j]), in[pnd][j]));
if(in[u][j] < in[v][j]) seg[j].upd(1, 1, N, in[v][j], fn[v][j], df);
else seg[j].upd(1, 1, N, in[u][j], fn[u][j], df);
dep[rt].insert(make_pair(seg[j].query(1, 1, N, in[pnd][j], fn[pnd][j]), in[pnd][j]));
{
ll ans = 0;
set<pli>::iterator it = dep[rt].end();
if(it != dep[rt].begin()){
it--;
ans += (*it).fi;
}
if(it != dep[rt].begin()){
it--;
ans += (*it).fi;
}
superseg.upd(rt, ans);
}
}
edges[idx].se = nw;
last = superseg.que(1, N);
cout << last << '\n';
}
}
Compilation message (stderr)
diameter.cpp: In member function 'void segtree::upd(int, int, int, int, int, long long int)':
diameter.cpp:124:16: warning: suggest parentheses around '+' inside '>>' [-Wparentheses]
124 | int mid = l + r >> 1;
| ~~^~~
diameter.cpp: In member function 'long long int segtree::query(int, int, int, int, int)':
diameter.cpp:137:16: warning: suggest parentheses around '+' inside '>>' [-Wparentheses]
137 | int mid = l + r >> 1;
| ~~^~~
# | 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... |