#include <bits/stdc++.h>
using namespace std;
#define task "DIAMETER"
#define FOR(i, a, b) for (int i = (a); i <= (b); i++)
#define FOD(i, a, b) for (int i = (a); i >= (b); i--)
#define F first
#define S second
template<class X, class Y>
bool maximize(X &x, Y y) {
if (x < y) {
x = y;
return true;
}
return false;
}
const int N = (int)1e5 + 5;
int numNode, numQuery;
long long limit;
struct EDGE {
int u, v, c;
} edges[N];
pair<int, int> query[N];
typedef pair<int, long long> il;
namespace sub2 {
const int N = (int)5e3 + 5;
EDGE newEdges[N];
vector<il> adj[N];
long long res = 0;
int x = 1;
void dfs(int u, int p, long long cur) {
if (maximize(res, cur)) x = u;
for (il e : adj[u]) {
if (e.F == p) continue;
dfs(e.F, u, cur + e.S);
}
}
long long findDiameter() {
FOR(u, 1, numNode) adj[u].clear();
FOR(i, 1, numNode - 1) {
int u = newEdges[i].u, v = newEdges[i].v;
long long c = newEdges[i].c;
adj[u].push_back({v, c});
adj[v].push_back({u, c});
}
x = 1;
res = 0;
dfs(1, -1, 0);
dfs(x, -1, 0);
return res;
}
void solve() {
FOR(i, 1, numNode - 1) newEdges[i] = edges[i];
long long last = 0;
FOR(i, 1, numQuery) {
int curEdge = (1LL * query[i].F + last) % (numNode - 1) + 1;
long long curChange = (query[i].S + last) % limit;
newEdges[curEdge].c = curChange;
last = findDiameter();
cout << last << "\n";
}
}
}
typedef pair<long long, long long> pll;
namespace sub4 {
bool valid() {
FOR(i, 1, numNode - 1) {
int u = edges[i].u, v = edges[i].v;
if (u > v) swap(u, v);
if (v != u * 2 && v != u * 2 + 1) return false;
}
return true;
}
struct DATA {
int firstMax, secondMax, firstBranch, secondBranch;
} costToSon[N];
vector<il> adj[N];
int par[N];
void update(DATA &cur, long long val, int branch) {
if (val > cur.firstMax) {
if (branch == cur.firstBranch) cur.firstMax = val;
else {
cur.secondMax = cur.firstMax;
cur.secondBranch = cur.firstBranch;
cur.firstMax = val;
cur.firstBranch = branch;
}
}
else if (val > cur.secondMax) {
if (branch != cur.firstBranch) {
cur.secondMax = val;
cur.secondBranch = branch;
}
}
}
void dfs(int u, int p) {
for (il e : adj[u]) {
if (e.F == p) continue;
int v = e.F;
par[v] = u;
dfs(v, u);
long long cur = e.S + costToSon[v].firstMax;
update(costToSon[u], cur, v);
}
}
long long tree[4 * N];
void update(int id, int l, int r, int pos, long long val) {
if (l == r) {
tree[id] = val;
return;
}
int mid = (l + r) >> 1;
if (pos <= mid) update(2 * id, l, mid, pos, val);
else update(2 * id + 1, mid + 1, r, pos, val);
tree[id] = max(tree[2 * id], tree[2 * id + 1]);
}
long long weight[N];
void updateQuery(int s) {
while (s > 1) {
update(costToSon[par[s]], costToSon[s].firstMax + weight[s], s);
update(1, 1, numNode, par[s], costToSon[par[s]].firstMax + costToSon[par[s]].secondMax);
s = par[s];
}
}
void solve() {
FOR(i, 1, numNode - 1) {
int u = edges[i].u, v = edges[i].v;
long long c = edges[i].c;
adj[u].push_back({v, c});
adj[v].push_back({u, c});
}
FOR(i, 1, numNode) costToSon[i] = {0, 0};
dfs(1, -1);
FOR(i, 1, numNode) update(1, 1, numNode, i, costToSon[i].firstMax + costToSon[i].secondMax);
FOR(i, 1, numNode - 1) {
int u = edges[i].u, v = edges[i].v;
if (u > v) swap(u, v);
weight[v] = edges[i].c;
}
long long last = 0;
FOR(i, 1, numQuery) {
int curEdge = (1LL * query[i].F + last) % (numNode - 1) + 1;
long long curChange = (query[i].S + last) % limit;
int u = max(edges[curEdge].u, edges[curEdge].v);
weight[u] = curChange;
updateQuery(u);
last = tree[1];
cout << last << "\n";
}
}
}
int main() {
if (fopen(task".inp", "r")) {
freopen(task".inp", "r", stdin);
freopen(task".out", "w", stdout);
}
ios_base::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
cin >> numNode >> numQuery >> limit;
FOR(i, 1, numNode - 1) {
int u, v, c;
cin >> u >> v >> c;
edges[i] = {u, v, c};
}
FOR(i, 1, numQuery) {
cin >> query[i].F >> query[i].S;
}
if (max(numNode, numQuery) <= 5000 && limit <= 10000) sub2::solve();
else if (sub4::valid()) sub4::solve();
return 0;
}
Compilation message (stderr)
diameter.cpp: In function 'int main()':
diameter.cpp:186:16: warning: ignoring return value of 'FILE* freopen(const char*, const char*, FILE*)' declared with attribute 'warn_unused_result' [-Wunused-result]
186 | freopen(task".inp", "r", stdin);
| ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
diameter.cpp:187:16: warning: ignoring return value of 'FILE* freopen(const char*, const char*, FILE*)' declared with attribute 'warn_unused_result' [-Wunused-result]
187 | freopen(task".out", "w", stdout);
| ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~
# | 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... |