Submission #1302675

#TimeUsernameProblemLanguageResultExecution timeMemory
1302675AMel0nDynamic Diameter (CEOI19_diameter)C++20
100 / 100
2815 ms153304 KiB
#include <bits/stdc++.h>
using namespace std;
 
typedef long long ll;
#define FOR(i,N) for(ll i = 0; i < N; i++)
#define all(x) (x).begin(), (x).end()
#define F first
#define S second


constexpr ll INF = 1e18;
constexpr int MAXLOG = 18;
constexpr int MAXN = 1e5 + 5;

int N, Q; 
ll W;
vector<pair<int,int>> adj[MAXN];
ll wt[MAXN];
pair<int,int> edge[MAXN];

int in[MAXLOG][MAXN], out[MAXLOG][MAXN], dep[MAXLOG][MAXN], anc[MAXLOG][MAXN], child[MAXLOG][MAXN];
int cnt[MAXLOG];

multiset<ll> cenbest[MAXN];
ll chbest[MAXLOG][MAXN];
priority_queue<pair<ll,int>> best;

int sz[MAXN];
bool del[MAXN];

ll st[MAXLOG][MAXN*4], lazy[MAXLOG][MAXN*4];

inline void pushdown(int t, int tl, int tr, int i) {
    if (lazy[t][i]) {
        st[t][i] += lazy[t][i];
        if (tl != tr) {
            lazy[t][i * 2] += lazy[t][i];
            lazy[t][i * 2 + 1] += lazy[t][i];
        }
        lazy[t][i] = 0;
    }
}

inline void update(int t, ll v, int l, int r, int tl = 0, int tr = N-1, int i = 1) {
    pushdown(t, tl, tr, i);
    if (l > r) return ;
    if (tl == l && tr == r) {
        st[t][i] += v;
        if (tl != tr) {
            lazy[t][i * 2] += v;
            lazy[t][i * 2 + 1] += v;
        }
        return ;
    }
    int tm = (tl + tr) / 2;
    update(t, v, l, min(r, tm), tl, tm, i * 2);
    update(t, v, max(l, tm + 1), r, tm + 1, tr, i * 2 + 1);
    st[t][i] = max(st[t][i * 2], st[t][i * 2 + 1]);
}

inline ll query(int t, int l, int r, int tl = 0, int tr = N-1, int i = 1) {
    pushdown(t, tl, tr, i);
    if (l > r) return 0;
    if (tl == l && tr == r) return st[t][i];
    int tm = (tl + tr) / 2;
    return max(query(t, l, min(r, tm), tl, tm, i * 2), query(t, max(l, tm + 1), r, tm + 1, tr, i * 2 + 1));
}

inline int dfsSZ(int v, int p) {
    sz[v] = 1;
    for(const auto &u: adj[v]) {
        if (del[u.F] || u.F == p) continue;
        sz[v] += dfsSZ(u.F, v);
    }
    return sz[v];
}

inline int dfsCEN(int v, int p, int treeSZ) {
    for(const auto &u: adj[v]) {
        if (del[u.F] || u.F == p || sz[u.F] * 2 <= treeSZ) continue;
        return dfsCEN(u.F, v, treeSZ);
    }
    return v;
}

inline void dfs(int t, int v, int p, ll d, int cen, int ch) {
    dep[t][v] = dep[t][p] + 1;
    child[t][v] = ch;
    anc[t][v] = cen;
    in[t][v] = cnt[t]++;
    update(t, d, in[t][v], in[t][v]);
    for(const auto &u: adj[v]) {
        if (u.F == p || del[u.F]) continue;
        dfs(t, u.F, v, d + wt[u.S], cen, ch);
    }
    out[t][v] = cnt[t];
}

inline ll calcbest(int cen) {
    if (cenbest[cen].size() == 1) {
        return *cenbest[cen].begin();
    }
    auto it = cenbest[cen].end();
    ll a = *--it;
    ll b = *--it;
    return a + b;
}

inline void build(int v = 0, int t = 0) {
    int treeSZ = dfsSZ(v, v);
    if (treeSZ <= 1) return ;
    int cen = dfsCEN(v, v, treeSZ);

    for(const auto &u: adj[cen]) {
        if (del[u.F]) continue;
        dfs(t, u.F, cen, wt[u.S], cen, u.F);
        ll q = query(t, in[t][u.F], out[t][u.F]-1);
        cenbest[cen].insert(q);
        chbest[t][u.F] = q;
    }
    best.emplace(calcbest(cen), cen);

    del[cen] = true;
    for(const auto &u: adj[cen]) {
        if (del[u.F]) continue;
        build(u.F, t + 1);
    }
}


signed main() {
    cin.tie(0); ios::sync_with_stdio(false);
    cin >> N >> Q >> W;
    FOR(i, MAXLOG) FOR(j, MAXN) anc[i][j] = -1;
    FOR(i, N-1) {
        int a, b;
        cin >> a >> b >> wt[i];
        a--; b--;
        edge[i] = {a, b};
        adj[a].emplace_back(b, i);
        adj[b].emplace_back(a, i);
    }
    build();

    ll last = 0;
    FOR(i, Q) {
        int d;
        ll e;
        cin >> d >> e;
        d = (d + last) % (N-1);
        e = (e + last) % W;
        ll upd = e - wt[d];
        wt[d] = e;
        auto [u, v] = edge[d];
        FOR(t, MAXLOG) {
            if (anc[t][u] == anc[t][v] && anc[t][u] != -1 && anc[t][v] != -1 || (anc[t][v] == u || anc[t][u] == v)) {
                if (dep[t][v] < dep[t][u]) swap(u, v);
                update(t, upd, in[t][v], out[t][v]-1);
                int ch = child[t][v];
                int cen = anc[t][v];
                cenbest[cen].erase(cenbest[cen].find(chbest[t][ch]));
                chbest[t][ch] = query(t, in[t][ch], out[t][ch]-1);
                cenbest[cen].insert(chbest[t][ch]);
                best.emplace(calcbest(cen), cen);
            }
        }
        while (true) {
            if (best.top().F != calcbest(best.top().S)) best.pop();
            else break;
        }
        last = best.top().F;
        cout << last << '\n';
    }
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...