Submission #1368492

#TimeUsernameProblemLanguageResultExecution timeMemory
1368492domiDynamic Diameter (CEOI19_diameter)C++20
100 / 100
206 ms88800 KiB
#include <bits/stdc++.h>

#define int long long
#define fi first
#define se second

#define sz(a) (int)((a).size())
#define all(a) (a).begin(), (a).end()

#define lsb(x) (x & (-x))
#define vi vector<int>
#define YES { cout << "YES" << endl; return; }
#define NO { cout << "NO" << endl; return; }

using ll = long long;
using pii = std::pair<int, int>;

const int NMAX = 1e5;
const int INF = 1e16;

using namespace std;

namespace DynamicDiameter {
    vector<pair<int, int>> T[NMAX + 5];
    int event[2 * NMAX + 5], timer = 0;
    int weights[NMAX + 5], dep[NMAX + 5];
    int tin[NMAX + 5], tout[NMAX + 5];

    inline void add_edge(int u, int v, int w) {
        T[u].push_back({v, w});
        T[v].push_back({u, w});
    }

    void dfs(int nod, int p = -1) {
        tin[nod] = ++timer;
        event[timer] = nod;
        for (auto &[son, w] : T[nod]) {
            if (son == p) continue;
            
            dep[son] = dep[nod] + w;
            weights[son] = w;
            dfs(son, nod);
            event[++timer] = nod;
        }
        tout[nod] = timer;
    }

    struct node_t {
        pair<int, int> max_depth;
        pair<int, int> min_depth;
        pair<int, int> ab;
        pair<int, int> bc;
        int diam;
        bool is_null;
        node_t() : max_depth({-INF, -1}), min_depth({INF, -1}), ab({-INF, -1}), bc({-INF, -1}), diam(0), is_null(true) {}

        static node_t merge(const node_t l, const node_t r) {
            if (l.is_null) return r;
            if (r.is_null) return l;

            node_t res;
            res.is_null = false;
            res.max_depth = max(l.max_depth, r.max_depth);
            res.min_depth = min(l.min_depth, r.min_depth);

            res.ab = max({l.ab, r.ab, {l.max_depth.fi - 2 * r.min_depth.fi, r.max_depth.se}});
            res.bc = max({l.bc, r.bc, {r.max_depth.fi - 2 * l.min_depth.fi, l.max_depth.se}});
            res.diam = max({l.diam, r.diam, l.max_depth.fi + r.bc.fi, r.max_depth.fi + l.ab.fi});
            return res;
        }
    };

    node_t aint[8 * NMAX + 5];
    int lazy[8 * NMAX + 5];

    void build(int nod = 1, int st = 1, int dr = timer) {
        if (st == dr) {
            int u = event[st];
            aint[nod].is_null = false;
            aint[nod].max_depth = aint[nod].min_depth = {dep[u], u};
            aint[nod].ab = aint[nod].bc = {-dep[u], u};
            aint[nod].diam = 0;
            lazy[nod] = 0;
            return;
        }
        
        int m = (st + dr) >> 1;
        build(2 * nod, st, m);
        build(2 * nod + 1, m + 1, dr);
        aint[nod] = node_t::merge(aint[2 * nod], aint[2 * nod + 1]);
        lazy[nod] = 0;
    }

    void init() {
        dfs(1);
        build();
    }

    void push(int nod, int st, int dr) {
        if (lazy[nod] != 0) {
            int& lz = lazy[nod];
            aint[nod].max_depth.fi += lz;
            aint[nod].min_depth.fi += lz;
            aint[nod].ab.fi -= lz;
            aint[nod].bc.fi -= lz;

            if (st != dr) {
                lazy[2 * nod] += lz;
                lazy[2 * nod + 1] += lz;
            }
            lazy[nod] = 0;
        }
    }

    void range_add(int l, int r, int v, int nod = 1, int st = 1, int dr = timer) {
        push(nod, st, dr);
        if (st > r || dr < l) return;
        if (l <= st && dr <= r) {
            lazy[nod] += v;
            push(nod, st, dr);
            return;
        }
        
        int m = (st + dr) >> 1;
        range_add(l, r, v, 2 * nod, st, m);
        range_add(l, r, v, 2 * nod + 1, m + 1, dr);
        aint[nod] = node_t::merge(aint[2 * nod], aint[2 * nod + 1]);
    }

    void AssignEdgeWeight(int u, int v, int e) {
        if (tin[u] > tin[v]) swap(u, v);
        int diff = e - weights[v];
        range_add(tin[v], tout[v], diff);
        weights[v] = e;
    }

    int get_diam() {
        return aint[1].diam;
    }
}

using namespace DynamicDiameter;

pair<int, int> edges[NMAX + 5];
int n, q, mod;

signed main() {
    cin.tie(nullptr)->sync_with_stdio(false);
    cin >> n >> q >> mod;

    for (int i = 0, u, v, w; i < n - 1; ++i) {
        cin >> u >> v >> w;
        edges[i] = {u, v};
        DynamicDiameter::add_edge(u, v, w);
    }

    DynamicDiameter::init();
    for (int i = 0, d, e, last = 0; i < q; ++i) {
        cin >> d >> e;

        d = (d + last) % (n - 1);
        e = (e + last) % mod;

        auto [u, v] = edges[d];
        DynamicDiameter::AssignEdgeWeight(u, v, e);
        last = DynamicDiameter::get_diam();
        cout << last << "\n";
    }
    return 0;
}
#Result Execution timeMemoryGrader output
Fetching results...
#Result Execution timeMemoryGrader output
Fetching results...
#Result Execution timeMemoryGrader output
Fetching results...
#Result Execution timeMemoryGrader output
Fetching results...
#Result Execution timeMemoryGrader output
Fetching results...
#Result Execution timeMemoryGrader output
Fetching results...