Submission #1098912

#TimeUsernameProblemLanguageResultExecution timeMemory
1098912RiverFlowDynamic Diameter (CEOI19_diameter)C++14
100 / 100
755 ms47400 KiB
#include <bits/stdc++.h>

#define nl "\n"
#define no "NO"
#define yes "YES"
#define fi first
#define se second
#define vec vector
#define task "main"
#define _mp make_pair
#define ii pair<int, int>
#define sz(x) (int)x.size()
#define all(x) x.begin(), x.end()
#define evoid(val) return void(std::cout << val)
#define FOR(i, a, b) for(int i = (a); i <= (b); ++i)
#define FOD(i, b, a) for(int i = (b); i >= (a); --i)
#define unq(x) sort(all(x)); x.resize(unique(all(x)) - x.begin())

using namespace std;

template<typename U, typename V> bool maxi(U &a, V b) {
    if (a < b) { a = b; return 1; } return 0;
}
template<typename U, typename V> bool mini(U &a, V b) {
    if (a > b) { a = b; return 1; } return 0;
}

const int N = (int)2e5 + 9;
const int mod = (int)1e9 + 7;

void prepare(); void main_code();

int main() {
    ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
    if (fopen(task".inp", "r")) {
        freopen(task".inp", "r", stdin);
        freopen(task".out", "w", stdout);
    }
    const bool MULTITEST = 0; prepare();
    int num_test = 1; if (MULTITEST) cin >> num_test;
    while (num_test--) { main_code(); }
}

void prepare() {};


int n, q;
long long w;

struct edge {
    int u, v;
    long long w;
    edge () {};
    edge (int _u, int _v, long long _w) {
        u = _u, v = _v, w = _w;
    }
    int get(int x) {
        return x ^ u ^ v;
    }
    bool operator < (const edge & other) {
        return w < other.w;
    }
} e[N];

vector<int> g[N];

int par[N];

long long d[N];
int s[N], tin[N], tout[N], cnt = 0;
void euler(int u, int p) {
    s[u] = 1;
    tin[u] = ++cnt;
    for(int id : g[u]) {
        int v = e[id].get(u);
        if (v != p) {
            par[v] = u;
            d[v] = d[u] + e[id].w;
            euler(v, u);
            s[u] += s[v];
        }
    }
    tout[u] = ++cnt;
}
int cc = 0, ch[N], hd[N], pos[N], nxt[N], base[N];
void hld(int u, int p) {
    pos[u] = ++cnt;
    base[cnt] = u;
    ch[u] = cc;
    if (hd[cc] == 0) hd[cc] = u;
    int mx = -1;
    for(int id : g[u]) {
        int v = e[id].get(u);
        if (v != p) {
            if (mx == -1 or s[v] > s[mx])
                mx = v;
        }
    }
    if (mx == -1) return ;
    nxt[u] = mx;
    hld(mx, u);
//    cerr << u << ' ' << mx << nl;
    for(int id : g[u]) {
        int v = e[id].get(u);
        if (v != p and v != mx) {
            ++cc;
            hld(v, u);
        }
    }
}


namespace IT {
    int arr[2 * N];
    struct segment_tree {
        int n;
        vector<long long> t, lz;
        segment_tree () {};
        segment_tree (int _n) {
            n = _n;
            t.resize(4 * n + 7);
            lz.resize(4 * n + 7);
        }
        void build(int id, int l, int r) {
            if (l == r) {
                t[id] = d[arr[l]];
                return ;
            }
            int m = (l + r) >> 1;
            build(id << 1, l, m);
            build(id << 1 | 1, m + 1, r);
            t[id] = max(t[id << 1], t[id << 1 | 1]);
        }
        void push(int id) {
            long long &v = lz[id];
            t[id << 1] += v;
            t[id << 1 | 1] += v;
            lz[id << 1] += v;
            lz[id << 1 | 1] += v;
            v = 0;
        }
        void update(int id, int l, int r, int u, int v, long long val) {
            if (l > v or r < u) return ;
            if (l >= u and r <= v) {
                t[id] += val;
                lz[id] += val;
                return ;
            }
            if (lz[id] != 0) push(id);
            int m = (l + r) >> 1;
            update(id << 1, l, m, u, v, val);
            update(id << 1 | 1, m + 1, r, u, v, val);
            t[id] = max(t[id << 1], t[id << 1 | 1]);
        }
        long long getMax(int id, int l, int r, int u, int v) {
            if (l > v or r < u)
                return 0;
            if (l >= u and r <= v)
                return t[id];
            if (lz[id] != 0) push(id);
            int m = (l + r) >> 1;
            return max(getMax(id << 1, l, m, u, v),
                       getMax(id << 1 | 1, m + 1, r, u, v));
        }
        long long get(int id, int l, int r, int p) {
            if (l == r) return t[id];
            if (lz[id] != 0) push(id);
            int m = (l + r) >> 1;
            return (p <= m ? get(id << 1, l, m, p) :
                             get(id << 1 | 1, m + 1, r, p));
        }
        long long get(int x) {
            return get(1, 1, n, x);
        }
        int fx(int id, int l, int r) {
            if (l == r) return arr[l];
            if (lz[id] != 0) push(id);
            int m = (l + r) >> 1;
            if (t[id << 1] >= t[id << 1 | 1])
                return fx(id << 1, l, m);
            return fx(id << 1 | 1, m + 1, r);
        }
    };
    segment_tree st;
    void init() {
        st = segment_tree(2 * n);
        for(int i = 1; i <= n; ++i) {
            arr[tin[i]] = arr[tout[i]] = i;
        }
//        FOR(i, 1, n) cout << d[i] << ' '; cout << nl;
//        FOR(i, 1, 2 * n) cout << arr[i] << ' '; cout << nl;
        st.build(1, 1, 2 * n);
    }
    long long getP(int t) {
        return st.get(1, 1, 2 * n, tin[t]);
    }
    long long get(int u, int t) {
        if (t == -1) {
            return st.getMax(1, 1, 2 * n, tin[u], tout[u]) - 2LL * st.get(tin[u]);
        }
        long long px = -2LL * st.get(tin[u]);
        long long r = 0;
        if (tin[u] != tin[t]) {
            r = max(r, st.getMax(1, 1, 2 * n, tin[u], tin[t] - 1));
        }
        if (tout[t] != tout[u]) {
            r = max(r, st.getMax(1, 1, 2 * n, tout[t] + 1, tout[u]));
        }
        return px + r;
    }
    void update(int l, int r, long long val) {
        st.update(1, 1, 2 * n, l, r, val);
    }
    int fx() {
        return st.fx(1, 1, 2 * n);
    }
};

struct segment_tree {
    // handle point update / get max
    // index theo base
    int n;
    vector<long long> t, lz;
    void init (int _n) {
        n = _n;
        t.resize(4 * n + 7);
        lz.resize(4 * n + 7);
    }
    void push(int id) {
        long long &v = lz[id];
        t[id << 1] += v;
        t[id << 1 | 1] += v;
        lz[id << 1] += v;
        lz[id << 1 | 1] += v;
        v = 0;
    }

    const long long INF = -(long long)1e17;
    void update(int id, int l, int r, int p, long long val) {
        if (l == r) {
            t[id] = val;
            return ;
        }
        if (lz[id]) push(id);
        int m = (l + r) >> 1;
        if (p <= m)
            update(id << 1, l, m, p, val);
        else
            update(id << 1 | 1, m + 1, r, p, val);
        t[id] = max(t[id << 1], t[id << 1 | 1]);
    }
    void update(int p, long long val) {
        update(1, 1, n, p, val);
    }

    void update(int id, int l, int r, int u, int v, long long val) {
        if (l > v or r < u) return ;
        if (l >= u and r <= v) {
            t[id] += val;
            lz[id] += val;
            return ;
        }
        if (lz[id]) push(id);
        int m = (l + r) >> 1;
        update(id << 1, l, m, u, v, val);
        update(id << 1 | 1, m + 1, r, u, v, val);
        t[id] = max(t[id << 1], t[id << 1 | 1]);
    }
    void update(int l, int r, long long val) {
        update(1, 1, n, l, r, val);
    }
    long long get(int id, int l, int r, int u, int v) {
        if (l > v or r < u) return INF;
        if (l >= u and r <= v) return t[id];
        if (lz[id]) push(id);
        int m = (l + r) >> 1;
        return max(get(id << 1, l, m, u, v),
                   get(id << 1 | 1, m + 1, r, u, v));
    }
    long long get(int l, int r) {
        return get(1, 1, n, l, r);
    }

} T;

int mxx[N];
void dfs2(int u, int p) {
    mxx[u] = pos[u];
    for(int id : g[u]) {
        int v = e[id].get(u);
        if (v != p) {
            dfs2(v,u);
            mxx[u]=max(mxx[u], mxx[v]);
        }
    }
}
void main_code() {
    cin >> n >> q >> w;
    for(int i = 1; i < n; ++i) {
        int u, v; long long c;
        cin >> u >> v >> c;
        e[i] = edge(u, v, c);
        g[u].push_back(i);
        g[v].push_back(i);
    }
    euler(1, 0);
    cnt = 0;
    FOR(i, 1, n) nxt[i] = -1;
    hld(1, 0);
    dfs2(1,0);
    IT::init();
    T.init(n);
    for(int i = 1; i <= n; ++i) {
        T.update(pos[i], IT::get(i, nxt[i]));
    }
    long long last = 0;
    FOR(i, 1, n - 1) {
        if (d[e[i].u] > d[e[i].v])
            swap(e[i].u, e[i].v);
    }
//    FOR(i, 1, n) cout << ch[i] << ' '; cout << nl;
//    FOR(i, 0, cc) cout << hd[i] << ' '; cout << nl;
//    return ;
    while (q--) {
        long long dj, ej;
        cin >> dj >> ej;
        dj = (dj + last) % (n - 1);
        ej = (ej + last) % w;
        ++dj; // edge thu dj
        long long vx = ej - e[dj].w;
        e[dj].w = ej;
//        cerr << "dj: " << dj << nl;
//        cerr << "vx: " << vx << nl;
        // update lai da
        int u = e[dj].u, v = e[dj].v;
        IT::update(tin[v], tout[v], vx);


//        if (ch[u] != ch[v]) {
//            T.update(pos[v], IT::get(v, nxt[v]));
//        }
        T.update(pos[v], mxx[v], -vx);
        for(int cur = v; ;) {
            cur = hd[ch[cur]];
            if (cur == 1) break ;
            int p = par[cur];
            T.update(pos[p], IT::get(p, nxt[p]));
            cur = p;
        }
        int k = IT::fx();
//        cerr << k << nl;
        //get cai d cua no luon
        long long dk = IT::getP(k);
//        cerr << "dk: " << dk << nl;
        long long ans = 0;
        for(int cur = k; ;) {
            int a = hd[ch[cur]];
            if (a != cur) {
                ans = max(ans, T.get(pos[a], pos[par[cur]]) + dk);
            }
            if (a == 1) break ;
            int p = par[a];
            ans = max(ans, IT::get(p, a) + dk);
            cur = p;
        }
        cout << ans << nl;
        last = ans;
    }
}


/*     Let the river flows naturally     */

Compilation message (stderr)

diameter.cpp: In function 'void main_code()':
diameter.cpp:335:13: warning: unused variable 'u' [-Wunused-variable]
  335 |         int u = e[dj].u, v = e[dj].v;
      |             ^
diameter.cpp: In function 'int main()':
diameter.cpp:36:16: warning: ignoring return value of 'FILE* freopen(const char*, const char*, FILE*)' declared with attribute 'warn_unused_result' [-Wunused-result]
   36 |         freopen(task".inp", "r", stdin);
      |         ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
diameter.cpp:37:16: warning: ignoring return value of 'FILE* freopen(const char*, const char*, FILE*)' declared with attribute 'warn_unused_result' [-Wunused-result]
   37 |         freopen(task".out", "w", stdout);
      |         ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~
#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...