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>
//#include "bits_stdc++.h"
//#include <ext/pb_ds/assoc_container.hpp>
//#include <ext/pb_ds/tree_policy.hpp>
#define endl '\n'
#define f first
#define s second
#define pb push_back
#define mp make_pair
#define lb lower_bound
#define ub upper_bound
#define input(x) scanf("%lld", &x);
#define input2(x, y) scanf("%lld%lld", &x, &y);
#define input3(x, y, z) scanf("%lld%lld%lld", &x, &y, &z);
#define input4(x, y, z, a) scanf("%lld%lld%lld%lld", &x, &y, &z, &a);
#define print(x, y) printf("%lld%c", x, y);
#define show(x) cerr << #x << " is " << x << endl;
#define show2(x,y) cerr << #x << " is " << x << " " << #y << " is " << y << endl;
#define show3(x,y,z) cerr << #x << " is " << x << " " << #y << " is " << y << " " << #z << " is " << z << endl;
#define all(x) x.begin(), x.end()
#define discretize(x) sort(x.begin(), x.end()); x.erase(unique(x.begin(), x.end()), x.end());
#define FOR(i, x, n) for (ll i =x; i<=n; ++i)
#define RFOR(i, x, n) for (ll i =x; i>=n; --i)
using namespace std;
mt19937_64 rnd(chrono::steady_clock::now().time_since_epoch().count());
//using namespace __gnu_pbds;
//#define ordered_set tree<int, null_type, less<int>, rb_tree_tag, tree_order_statistics_node_update>
//#define ordered_multiset tree<int, null_type, less_equal<int>, rb_tree_tag, tree_order_statistics_node_update>
typedef long long ll;
typedef long double ld;
typedef pair<ld, ll> pd;
typedef pair<string, ll> psl;
typedef pair<ll, ll> pi;
typedef pair<pi, ll> pii;
typedef pair<pi, pi> piii;
// This is grapevine but max length
// General
ll const MAXN = 100100;
ll n, q, u, v, w, t, maxw;
vector<pii> edges;
ll save[MAXN];
priority_queue<ll> ans, del;
// RURQ Segment Tree
struct node{
int s, e, m;
pi val;
ll lazy;
node *l, *r;
node (int S, int E)
{
s = S, e = E, m = (s+e)/2;
val = mp(0, s);
lazy = 0;
if(s != e)
{
l = new node(s, m);
r = new node(m+1, e);
}
}
void propogate()
{
if (lazy==0) return;
val.f+=lazy;
if (s != e){
l->lazy+=lazy;
r->lazy+=lazy;
}
lazy=0;
}
void update(int S, int E, ll V)
{
propogate();
if(s==S && e==E) lazy += V;
else{
if(E <= m) l->update(S, E, V);
else if (m < S) r->update(S, E, V);
else l->update(S, m, V),r->update(m+1, E, V);
l->propogate(),r->propogate();
val = max(l->val, r->val);
}
}
pi query(int S, int E)
{
if (S > E) return mp(0LL, -1LL);
propogate();
if(s == S && e == E) return val;
if(E <= m) return l->query(S, E);
else if(S >= m+1) return r->query(S, E);
else return max(l->query(S, m), r->query(m+1, E));
}
} *root[100005];
// centroid decomposition
ll label = -1;
ll sub[MAXN], lvl[MAXN], par[MAXN], m[MAXN], in[25][MAXN], out[25][MAXN], siz[MAXN];
vector<ll> V[MAXN];
bool vis[MAXN];
vector<ll> child[MAXN];
int dfs1(int u, int p, int l) {
sub[u] = 1; // Subtree size is 1
for (auto v : V[u]) {
if (vis[u]) continue; // Already added to centroid tree
if (v == p) continue;
sub[u] += dfs1(v, u, l); // Increase size of subtree
}
return sub[u];
}
int dfs2(int u, int p, int n) { // Pass in the size of the subtree
for (auto v : V[u]) {
if (vis[u]) continue; // Already added to centroid tree
if (v != p && sub[v] > n / 2) {
return dfs2(v, u, n); // DFS to that node
}
}
return u; // No child has size more than n/2, hence you are the centroid
}
void precomp(ll x, ll p = -1, ll l =0)
{
in[l][x] = ++label;
for (ll u: V[x]) if (u!=p && !vis[u]) precomp(u, x, l);
out[l][x] = label;
}
// Building from node u, with a parent p and level l
void build(int u, int p= -1, int l = 0) {
int n = dfs1(u, p, l); // Find the size of each subtree
int cent = dfs2(u, p, n); // Find the centroid
label = -1;
precomp(cent, -1, l);
root[cent] = new node(0, label);
//show(cent);
siz[cent] = label+1;
save[cent] = 0;
ans.push(0);
//show2(cent, label);
vis[cent] = 1;
//if (p == -1) p = cent; // Parent of root is yourself
par[cent] = p; // Set the parent of centroid to the previous centroid
lvl[cent] = l;
for (auto v : V[cent]) {
if (vis[v]) continue;
// If we have already added to centroid then we ignore
child[cent].pb(v);
build(v, cent, l + 1); // Recursively build each subtree
}
}
//To construct the centroid tree, call build(root, -1, 0);
void set_weight(ll i, ll w)
{
ll dw = w - edges[i].s;
ll u = edges[i].f.f, v=edges[i].f.s;
if (lvl[u] > lvl[v]) swap(u, v);
ll now = u, l = lvl[u];
while (now!= -1)
{
//show(now);
if (in[l][u] < in[l][v]) swap(u, v);
del.push(save[now]);
//show(2);
//show3(in[l][u], out[l][u], siz[now]);
root[now]->update(in[l][u], out[l][u], dw);
//show(1);
pi res = root[now]->query(0, siz[now]-1);
ll lo = 0, hi = child[now].size()-1;
while (lo!=hi)
{
ll mid = (lo+hi+1)/2;
if (in[l][child[now][mid]] <= res.s) lo = mid;
else hi = mid-1;
}
pi res2 = root[now]->query(0, in[l][child[now][lo]]-1);
res2= max(res2, root[now]->query(out[l][child[now][lo]]+1, siz[now]-1));
save[now] = res.f + res2.f;
ans.push(save[now]);
now = par[now];
l--;
}
edges[i].s = w;
}
int main()
{
input3(n, q, maxw);
for (ll i=0; i<n-1; ++i) vis[i] = 0;
for (ll i=0; i<n-1; ++i)
{
input3(u, v, w);
edges.pb(mp(mp(u, v), w));
V[u].pb(v);
V[v].pb(u);
}
//show(1);
build(1, -1, 0);
//show(1);
for (ll i=0; i<n-1; ++i)
{
ll val = edges[i].s;
edges[i].s = 0;
set_weight(i, val);
}
//show(1);
ll hashing = 0;
while (q--)
{
input2(u, w);
u = (u + hashing)%(n-1);
w = (w + hashing)%maxw;
set_weight(u, w);
while (del.size() && ans.top() == del.top())
{
ans.pop(); del.pop();
}
hashing = ans.top();
print(hashing, '\n');
}
return 0;
}
Compilation message (stderr)
diameter.cpp: In function 'int main()':
diameter.cpp:14:30: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
14 | #define input3(x, y, z) scanf("%lld%lld%lld", &x, &y, &z);
| ~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~
diameter.cpp:201:2: note: in expansion of macro 'input3'
201 | input3(n, q, maxw);
| ^~~~~~
diameter.cpp:14:30: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
14 | #define input3(x, y, z) scanf("%lld%lld%lld", &x, &y, &z);
| ~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~
diameter.cpp:205:3: note: in expansion of macro 'input3'
205 | input3(u, v, w);
| ^~~~~~
diameter.cpp:13:27: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
13 | #define input2(x, y) scanf("%lld%lld", &x, &y);
| ~~~~~^~~~~~~~~~~~~~~~~~~~
diameter.cpp:223:3: note: in expansion of macro 'input2'
223 | input2(u, w);
| ^~~~~~
# | 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... |