Submission #1108513

#TimeUsernameProblemLanguageResultExecution timeMemory
1108513crafticatDynamic Diameter (CEOI19_diameter)C++17
49 / 100
4737 ms389300 KiB
#include <bits/stdc++.h>

using namespace std;

using ll = long long;
template<typename T>
using V = vector<T>;
using vi = V<int>;
using vb = V<bool>;
using pi = pair<int,int>;

#define F0R(i,n) for (int i = 0; i < n;i++)
#define FOR(i, j, n) for(int i = j; i < n;i++)
#define ckmin(x,y) x = min(x,y)
#define f first
#define s second
#define pb push_back
#define sor(a,b) min(a,b), max(a,b)
constexpr int INF = 1e9;
const pi emp = {0, 0};

V<V<int>> g;

vb vis;
vi siz;

void calcSize(int x, int p) {
    siz[x] = 1;

    for (auto y : g[x]) {
        if (y == p || vis[y]) continue;

        calcSize(y, x);
        siz[x] += siz[y];
    }
}

int find_cen(int x, int p, int N) {
    for (auto y : g[x]) {
        if (y == p || vis[y]) continue;

        if (siz[y] * 2 > N)
            return find_cen(y,x,N);
    }

    return x;
}

struct Seg {
    Seg *left = nullptr, *right = nullptr;
    int l, r, mid;
    pi v;
    int lazy = 0;

    Seg(int l, int r, vi &ind) : l(l), r(r), mid((r + l) / 2 ) {
        if (r - l > 1) {
            left = new Seg(l,mid, ind);
            right = new Seg(mid, r, ind);

        } else
            v = {0,ind[l]};
    }
    void push() {
        if (lazy == 0) return;
        v.f += lazy;
        if (r -l > 1) {
            left->lazy += lazy;
            right->lazy += lazy;
        }
        lazy = 0;
    }

    void update(int a, int b, int u) {
        push();

        if (b <= l || a >= r) return;
        if (a <= l && b >= r) {
            lazy += u;
            push();
            return;
        }
        left->update(a,b, u);
        right->update(a,b,u);
        v = max(left->v, right->v);
    }
    pi q(int a, int b) {
        push();

        if (b <= l || a >= r) return emp;
        if (a <= l && b >= r) return v;
        return max(left->q(a,b), right->q(a,b));
    }
};

struct Cent {
    vi child;
    map<int, int> in_order, out_order;
    map<int,int> mainSubTree;
    Seg* seg;
    Cent *par = nullptr;
    int centroid;

    Cent(int x) : centroid(x) {
        int t = 0;
        dfs(x, -1, t);
        seg = new Seg(0, in_order.size(), child);
    }

    void dfs(int x, int p, int &t, int subTree = -1) {
        in_order[x] = t++;
        child.pb(x);
        mainSubTree[x] = subTree;

        for (auto y : g[x]) {
            if (y == p || vis[y]) continue;
            dfs(y,x, t,subTree == -1 ? y : subTree);
        }
        out_order[x] = t;
    }

    void update(int a, int p, int u) {
        if (in_order[a] < in_order[p]) swap(a,p);
        seg->update(in_order[a], out_order[a], u);

        if (par) par->update(a,p,u);
    }

    pi q(int node, int subTree) {
        // Get a subtree
        int distanceToCen = seg->q(in_order[node], in_order[node] + 1).f;
        pi distance = max(seg->q(0, in_order[mainSubTree[node]]), seg->q(out_order[mainSubTree[node]],in_order.size()));

        distance.f += distanceToCen;
        return max(distance, par ? par->q(node, centroid) : emp);
    }
};

V<Cent*> centroids;
vi centroidDepth;

Cent* cent_decomp(int x, int d = 0) {
    calcSize(x, -1);
    int cen = find_cen(x, -1, siz[x]);

    centroids[cen] = new Cent(cen);
    centroidDepth[cen] = d;
    vis[cen] = true;

    for (auto y : g[cen]) {
        if (vis[y]) continue;
        cent_decomp(y, d + 1)->par = centroids[cen];
    }
    return centroids[cen];
}

map<pi, int> weights;

void updateWeight(int a, int b, int newW) {
    if (a > b) swap(a,b);
    int diff = newW - weights[{a,b}];
    int centPar = a, centChild = b;
    if (centroidDepth[centPar] > centroidDepth[centChild]) swap(centPar, centChild);
    centroids[centPar]->update(centChild, centPar, diff);

    weights[{a,b}] = newW;
}

pi queryFar(int x) {
    return centroids[x]->q(x, -1);
}

// 278
int main() {
    ios_base::sync_with_stdio(false); cin.tie(nullptr);

    int n, q, cMAX; cin >> n >> q >> cMAX;
    g.resize(n + 1);

    V<pi> edges(n);
    vi initC(n);

    F0R(i, n - 1) {
        int a, b, c; cin >> a >> b >> c;
        g[a].pb(b);
        g[b].pb(a);
        edges[i] = {a,b};
        initC[i] = c;
    }

    centroids.resize(n + 1);
    centroidDepth.resize(n + 1);
    vis.resize(n + 1);
    siz.resize(n + 1);
    cent_decomp(1);

    F0R(i, n - 1)
        updateWeight(edges[i].f, edges[i].s, initC[i]);

    int last = 0;
    F0R(i, q) {
        int e, c; cin >> e >> c;
        e = (e + last) % (n - 1);
        c = (last + c) % (cMAX);

        auto [a,b] = edges[e];
        updateWeight(a, b, c);
        int f1 = queryFar(1).s;
        int results = queryFar(f1).f;

        cout << results << "\n";
        last = results;
    }

    return 0;
}
#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...