Submission #1325585

#TimeUsernameProblemLanguageResultExecution timeMemory
1325585nxk02102010Dynamic Diameter (CEOI19_diameter)C++20
49 / 100
1301 ms148672 KiB
#include <bits/stdc++.h>
using namespace std;

static const int MAXN = 100000;

int n, qu, hihi;

vector<pair<int,int>> adj[MAXN+5];
int dep[MAXN+5], sub[MAXN+5], anc[MAXN+5];
bool vis[MAXN+5];

inline void ulang(int cur, int par){
    sub[cur] = 1;
    for(const auto &x : adj[cur]){
        int v = x.first;
        if(v == par) continue;
        if(vis[v]){
            sub[v] = 0;
            continue;
        }
        ulang(v, cur);
        sub[cur] += sub[v];
    }
}

inline int centro(int cur, int par, int sz){
    for(const auto &x : adj[cur]){
        int v = x.first;
        if(v == par || vis[v]) continue;
        if(sub[v] >= sz/2) return centro(v, cur, sz);
    }
    return cur;
}

array<int,3> mp[MAXN+5][20];
int cnt;
long long distv[MAXN+5];

inline void euler(int cur, int par, long long tot, int asal, int lvl){
    distv[++cnt] = tot;
    mp[cur][lvl] = {cnt, 0, asal};
    for(const auto &x : adj[cur]){
        int v = x.first;
        if(v == par || vis[v]) continue;
        euler(v, cur, tot + x.second, asal, lvl);
    }
    mp[cur][lvl][1] = cnt;
}

struct seg{
    int l, r;
    long long mx, lz;
    seg *lf, *rg;

    void build(int L, int R){
        l = L; r = R;
        lz = 0;
        if(l == r){
            mx = distv[l];
            lf = rg = nullptr;
            return;
        }
        int mid = (l+r)>>1;
        lf = new seg();
        rg = new seg();
        lf->build(l, mid);
        rg->build(mid+1, r);
        mx = max(lf->mx, rg->mx);
    }

    inline void apply(long long v){
        lz += v;
        mx += v;
    }

    inline void push(){
        if(lz && l != r){
            lf->apply(lz);
            rg->apply(lz);
            lz = 0;
        }
    }

    void update(int ql, int qr, long long v){
        if(qr < l || r < ql) return;
        if(ql <= l && r <= qr){
            apply(v);
            return;
        }
        push();
        lf->update(ql, qr, v);
        rg->update(ql, qr, v);
        mx = max(lf->mx, rg->mx);
    }

    inline long long semua() const{
        return mx;
    }
};

vector<seg*> isi[MAXN+5];
multiset<long long> cari[MAXN+5];
multiset<long long> ans;

void solve(int cur, int prv){
    ulang(cur, -1);
    int root = centro(cur, prv, sub[cur]);

    vis[root] = true;
    dep[root] = dep[prv] + 1;
    anc[root] = prv;

    int id = -1;
    for(const auto &x : adj[root]){
        int v = x.first;
        if(vis[v]) continue;
        cnt = 0;
        ++id;
        euler(v, root, x.second, id, dep[root]);
        seg *st = new seg();
        st->build(1, cnt);
        isi[root].push_back(st);
        cari[root].insert(st->semua());
    }

    for(const auto &x : adj[root]){
        int v = x.first;
        if(!vis[v]) solve(v, root);
    }
}

inline long long mul(int idx){
    auto &ms = cari[idx];
    if(ms.empty()) return 0;
    auto it = ms.end(); --it;
    long long res = *it;
    if(ms.size() >= 2){
        --it;
        res += *it;
    }
    return res;
}

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

    cin >> n >> qu >> hihi;

    vector<array<int,3>> edge(n);
    for(int i=1;i<n;i++){
        int u,v,w;
        cin >> u >> v >> w;
        edge[i] = {u,v,w};
        adj[u].push_back({v,w});
        adj[v].push_back({u,w});
    }

    solve(1, 0);

    for(int i=1;i<=n;i++){
        ans.insert(mul(i));
    }

    long long lastt = 0;
    while(qu--){
        int d,e;
        cin >> d >> e;
        d = (d + lastt) % (n-1) + 1;
        e = (e + lastt) % hihi;

        int u = edge[d][0];
        int v = edge[d][1];
        int oldw = edge[d][2];

        if(dep[u] > dep[v]) swap(u,v);
        long long delta = e - oldw;

        int cur = u;
        while(cur){
            auto uu = mp[u][dep[cur]];
            auto vv = mp[v][dep[cur]];
            if(uu[0] < vv[0]) swap(uu, vv);

            ans.erase(ans.find(mul(cur)));

            seg *st = isi[cur][uu[2]];
            cari[cur].erase(cari[cur].find(st->semua()));
            st->update(uu[0], uu[1], delta);
            cari[cur].insert(st->semua());

            ans.insert(mul(cur));
            cur = anc[cur];
        }

        edge[d][2] = e;
        lastt = *ans.rbegin();
        cout << lastt << '\n';
    }
    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...