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>
#pragma GCC optimize("O3", "unroll-loops")
using namespace std;
#define ll long long
const int MX = 1e5 + 69;
const int LG = 17;
const ll inf = 4e18 + 69;
#define ll long long
int n, q; ll wtwtwt;
vector<pair<pair<int, int>, ll> > edges;
vector<int> adj[MX];
struct SegmentTree{
ll st[MX * 2], lz[MX * 2];
#define cm (cl + cr) / 2
#define lc nd + 1
#define rc nd + 2 * (cm - cl + 1)
inline void prop(int nd, int cl, int cr){
if(lz[nd]){
st[nd] += lz[nd];
if(cl != cr){
lz[lc] += lz[nd];
lz[rc] += lz[nd];
}
lz[nd] = 0;
}
}
inline void upd(int nd, int cl, int cr, int lf, int rg, ll vl){
prop(nd, cl, cr);
if(cr < lf || rg < cl) return;
if(lf <= cl && cr <= rg){
lz[nd] += vl;
prop(nd, cl, cr);
return;
}
upd(lc, cl, cm, lf, rg, vl);
upd(rc, cm + 1, cr, lf, rg, vl);
st[nd] = max(st[lc], st[rc]);
}
inline ll que(int nd, int cl, int cr, int lf, int rg){
prop(nd, cl, cr);
if(cr < lf || rg < cl) return -1;
if(lf <= cl && cr <= rg) return st[nd];
ll L = que(lc, cl, cm, lf, rg);
ll R = que(rc, cm + 1, cr, lf, rg);
return max(L, R);
}
} st[LG];
struct SegmentTreeIterative{
ll st[MX << 1];
inline void upd(int ps, ll vl){
for(ps += MX, st[ps] = vl, ps >>= 1; ps > 0; ps >>= 1) st[ps] = max(st[ps << 1], st[ps << 1 | 1]);
}
inline ll que(ll lf, ll rg){
ll rs = 0ll;
for(lf += MX, rg += MX + 1; lf < rg; lf >>= 1, rg >>= 1){
if(lf & 1) rs = max(st[lf ++], rs);
if(rg & 1) rs = max(rs, st[-- rg]);
}
return rs;
}
} stdp;
bool vis[MX], dead[MX];
int sz[MX];
inline void dfssz(int nw, int bf){
sz[nw] = 1;
for(int nx : adj[nw]) if(nx != bf && !dead[nx]){
dfssz(nx, nw);
sz[nw] += sz[nx];
}
}
int cent = -1, ccsz = 0;
inline void dfscent(int nw, int bf){
for(int nx : adj[nw]) if(nx != bf && !dead[nx]) dfscent(nx, nw);
if(cent == -1 && sz[nw] >= (ccsz + 1) / 2) cent = nw;
}
int layer = 0, tin[MX][LG], tim[LG], tout[MX][LG], rt[MX][LG], par[MX][LG], layer_id[MX];
inline void init(int nw, int bf){
rt[nw][layer] = cent;
tin[nw][layer] = ++ tim[layer];
par[nw][layer] = bf;
for(int nx : adj[nw]) if(nx != bf && !dead[nx]) init(nx, nw);
tout[nw][layer] = tim[layer];
}
vector<pair<int, int> > adj_root[MX];
inline void findCentroid(int nw){
dfssz(nw, 0);
cent = -1, ccsz = sz[nw];
dfscent(nw, 0);
init(cent, 0); layer_id[cent] = layer;
for(int nx : adj[cent]) if(!dead[nx])
adj_root[cent].push_back({tin[nx][layer], nx});
sort(adj_root[cent].begin(), adj_root[cent].end());
dead[cent] = 1;
for(int nx : adj[cent]) if(!dead[nx]){
layer ++;
findCentroid(nx);
layer --;
}
}
set<pair<ll, int> > dp[MX];
int main(){
scanf("%d %d %lld", &n, &q, &wtwtwt);
for(int i = 1; i < n; i ++){
int u, v; ll w;
scanf("%d %d %lld", &u, &v, &w);
adj[u].push_back(v);
adj[v].push_back(u);
edges.push_back({{u, v}, w});
}
findCentroid(1);
for(auto e : edges){
int u = e.first.first, v = e.first.second; ll w = e.second;
for(int j = 0; j < LG; j ++){
if(rt[u][j] != rt[v][j]) break;
if(tin[u][j] < tin[v][j]) swap(u, v);
st[j].upd(1, 1, n, tin[u][j], tout[u][j], w);
}
}
for(int i = 1; i <= n; i ++){
for(pair<int, int> nx : adj_root[i])
dp[i].insert({st[layer_id[i]].que(1, 1, n, tin[nx.second][layer_id[i]], tout[nx.second][layer_id[i]]), tin[nx.second][layer_id[i]]});
ll res = 0ll;
auto it = dp[i].end();
for(int _ = 0; _ < 2; _ ++) if(it != dp[i].begin()){
it = prev(it);
res += (*it).first;
}
stdp.upd(i, res);
}
ll last_answer = 0ll;
for(; q --;){
int ee; ll wt; scanf("%d %lld", &ee, &wt);
ee = (int)((ee + last_answer) % (n - 1));
wt = (wt + last_answer) % wtwtwt;
int u = edges[ee].first.first, v = edges[ee].first.second; ll wtchange = wt - edges[ee].second;
for(int j = 0; j < LG; j ++){
if(rt[u][j] != rt[v][j]) break;
if(tin[u][j] < tin[v][j]) swap(u, v);
int uid = lower_bound(adj_root[rt[u][j]].begin(), adj_root[rt[u][j]].end(), make_pair(tin[u][j] + 1, -1)) - adj_root[rt[u][j]].begin();
int anc = adj_root[rt[u][j]][uid - 1].second;
dp[rt[u][j]].erase(make_pair(st[j].que(1, 1, n, tin[anc][j], tout[anc][j]), tin[anc][j]));
st[j].upd(1, 1, n, tin[u][j], tout[u][j], wtchange);
dp[rt[u][j]].insert(make_pair(st[j].que(1, 1, n, tin[anc][j], tout[anc][j]), tin[anc][j]));
ll res = 0ll;
auto it = dp[rt[u][j]].end();
for(int _ = 0; _ < 2; _ ++) if(it != dp[rt[u][j]].begin()){
it = prev(it);
res += (*it).first;
}
stdp.upd(rt[u][j], res);
}
edges[ee].second = wt;
last_answer = stdp.que(1, n);
printf("%lld\n", last_answer);
}
return 0;
}
Compilation message (stderr)
diameter.cpp: In function 'int main()':
diameter.cpp:121:7: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
121 | scanf("%d %d %lld", &n, &q, &wtwtwt);
| ~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diameter.cpp:124:8: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
124 | scanf("%d %d %lld", &u, &v, &w);
| ~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~
diameter.cpp:157:23: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
157 | int ee; ll wt; scanf("%d %lld", &ee, &wt);
| ~~~~~^~~~~~~~~~~~~~~~~~~~~
# | 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... |