Submission #1369886

#TimeUsernameProblemLanguageResultExecution timeMemory
1369886LOLOLODynamic Diameter (CEOI19_diameter)C++20
0 / 100
65 ms46456 KiB
#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

typedef long long ll;

const ll INF = 1e18;

struct Edge {
    int to;
    ll weight;
    int id;
};

struct Node {
    ll maxD, minD, ansL, ansR, diameter;

    Node() {
        maxD = -INF; minD = INF;
        ansL = ansR = diameter = 0;
    }

    void apply(ll v) {
        maxD += v;
        minD += v;
        ansL -= v;
        ansR -= v;
    }
};

int n, q;
ll w;
vector<Edge> adj[100005];
pair<int, int> edges[100005];
ll edge_weights[100005];
int in[100005], out[100005], timer;
ll initial_depth[200005];
int tour[200005];

void dfs(int u, int p, ll d) {
    in[u] = ++timer;
    tour[timer] = u;
    initial_depth[timer] = d;
    for (auto& e : adj[u]) {
        if (e.to != p) {
            edges[e.id] = {u, e.to}; // Lưu lại để biết node nào là con
            dfs(e.to, u, d + e.weight);
            tour[++timer] = u;
            initial_depth[timer] = d;
        }
    }
}

Node tree[800005];
ll lazy[800005];

Node merge(const Node& a, const Node& b) {
    Node res;
    res.maxD = max(a.maxD, b.maxD);
    res.minD = min(a.minD, b.minD);
    res.ansL = max({a.ansL, b.ansL, a.maxD - 2 * b.minD});
    res.ansR = max({a.ansR, b.ansR, b.maxD - 2 * a.minD});
    res.diameter = max({a.diameter, b.diameter, a.ansL + b.maxD, a.maxD + b.ansR});
    return res;
}

void push(int v) {
    if (lazy[v] != 0) {
        tree[2 * v].apply(lazy[v]);
        lazy[2 * v] += lazy[v];
        tree[2 * v + 1].apply(lazy[v]);
        lazy[2 * v + 1] += lazy[v];
        lazy[v] = 0;
    }
}

void build(int v, int tl, int tr) {
    if (tl == tr) {
        tree[v].maxD = tree[v].minD = initial_depth[tl];
        tree[v].ansL = -initial_depth[tl];
        tree[v].ansR = -initial_depth[tl];
        tree[v].diameter = 0;
    } else {
        int tm = (tl + tr) / 2;
        build(2 * v, tl, tm);
        build(2 * v + 1, tm + 1, tr);
        tree[v] = merge(tree[2 * v], tree[2 * v + 1]);
    }
}

void update(int v, int tl, int tr, int l, int r, ll add) {
    if (l > r) return;
    if (l == tl && r == tr) {
        tree[v].apply(add);
        lazy[v] += add;
    } else {
        push(v);
        int tm = (tl + tr) / 2;
        update(2 * v, tl, tm, l, min(r, tm), add);
        update(2 * v + 1, tm + 1, tr, max(l, tm + 1), r, add);
        tree[v] = merge(tree[2 * v], tree[2 * v + 1]);
    }
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);

    cin >> n >> q >> w;
    for (int i = 0; i < n - 1; i++) {
        int u, v;
        ll c;
        cin >> u >> v >> c;
        adj[u].push_back({v, c, i});
        adj[v].push_back({u, c, i});
        edge_weights[i] = c;
    }

    dfs(1, 0, 0);
    int m = timer;
    build(1, 1, m);

    ll last = 0;
    while (q--) {
        ll d_idx, e_val;
        cin >> d_idx >> e_val;
        int idx = (d_idx + last) % (n - 1);
        ll new_w = (e_val + last) % w;

        int u = edges[idx].first;
        int v = edges[idx].second;
        // v luôn là con của u theo cách DFS lưu edges
        
        // Tìm cây con của v trong Euler Tour
        // v là con của u, nên khi update cạnh (u, v), 
        // ta update toàn bộ subtree của v.
        // Tìm vị trí bắt đầu và kết thúc của subtree v
        // Trong DFS trên, in[v] là lần đầu thăm, sau đó là out[v]
        // Tuy nhiên Euler tour này lưu cả đường về, nên subtree của v
        // nằm trọn trong [in[v], out[v]]
        
        ll diff = new_w - edge_weights[idx];
        edge_weights[idx] = new_w;
        update(1, 1, m, in[v], out[v], diff);

        last = tree[1].diameter;
        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...