Submission #1074107

#TimeUsernameProblemLanguageResultExecution timeMemory
1074107_callmelucianDynamic Diameter (CEOI19_diameter)C++14
100 / 100
2545 ms209316 KiB
#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef long double ld;
typedef pair<ll,ll> pl;
typedef pair<int,int> pii;
typedef tuple<int,int,ll> tt;

#define all(a) a.begin(), a.end()
#define filter(a) a.erase(unique(all(a)), a.end())

const int mn = 1e5 + 5;
const int LOG = 19;

struct IT {
    vector<pl> tr;

    IT() {}
    IT (int sz) : tr(4 * sz) {}

    void update (int pos, ll val, int k, int l, int r) {
        if (pos < l || r < pos) return;
        if (l == r) {
            tr[k] = {val, l};
            return;
        }
        int mid = (l + r) >> 1;
        update(pos, val, 2 * k, l, mid);
        update(pos, val, 2 * k + 1, mid + 1, r);
        tr[k] = max(tr[2 * k], tr[2 * k + 1]);
    }

    pl query (int a, int b, int k, int l, int r) {
        if (b < l || r < a) return {0, 0};
        if (a <= l && r <= b) return tr[k];
        int mid = (l + r) >> 1;
        return max(query(a, b, 2 * k, l, mid), query(a, b, 2 * k + 1, mid + 1, r));
    }
} tree[mn], childDiam[mn];

struct lazyIT {
    vector<ll> tr, lazy;

    lazyIT() {}
    lazyIT (int sz) : tr(4 * sz), lazy(4 * sz) {}

    ll get (int k) { return tr[k] + lazy[k]; }

    void pushDown (int k) {
        lazy[2 * k] += lazy[k], lazy[2 * k + 1] += lazy[k], lazy[k] = 0;
        tr[k] = max(get(2 * k), get(2 * k + 1));
    }

    void update (int a, int b, ll inc, int k, int l, int r) {
        if (b < l || r < a) return;
        if (a <= l && r <= b) {
            lazy[k] += inc;
            return;
        }
        pushDown(k);
        int mid = (l + r) >> 1;
        update(a, b, inc, 2 * k, l, mid);
        update(a, b, inc, 2 * k + 1, mid + 1, r);
        tr[k] = max(get(2 * k), get(2 * k + 1));
    }

    ll query (int a, int b, int k, int l, int r) {
        if (b < l || r < a) return 0;
        if (a <= l && r <= b) return get(k);
        pushDown(k);
        int mid = (l + r) >> 1;
        return max(query(a, b, 2 * k, l, mid), query(a, b, 2 * k + 1, mid + 1, r));
    }
} depth[mn];

ll in[LOG][mn], out[LOG][mn], ctroid[LOG][mn];
ll diameter[mn], sz[mn], sztr[mn], timeDfs;
vector<int> child[mn];
vector<pl> adj[mn];
bool del[mn];

void calcDfs (int u, int p, int root, int layer) {
    in[layer][u] = ++timeDfs;
    for (auto [v, w] : adj[u]) {
        if (del[v] || v == p) continue;
        calcDfs(v, u, root, layer);
        depth[root].update(in[layer][v], out[layer][v], w, 1, 1, sztr[root]);
    }
    out[layer][u] = timeDfs;
}

int szDfs (int u, int p) {
    sz[u] = 1;
    for (auto [v, w] : adj[u])
        if (!del[v] && v != p) sz[u] += szDfs(v, u);
    return sz[u];
}

int centroid (int u, int p, int layer, int cursz) {
    for (auto [v, w] : adj[u])
        if (!del[v] && v != p && sz[v] > cursz / 2)
            return centroid(v, u, layer, cursz);
    return u;
}

ll twoBest (IT &tr, int sz) {
    ll best, pos; tie(best, pos) = tr.query(0, sz, 1, 0, sz);
    tr.update(pos, 0, 1, 0, sz);
    ll sec = tr.query(0, sz, 1, 0, sz).first;
    tr.update(pos, best, 1, 0, sz);
    return best + sec;
}

ll getDiam (int layer, int u) { return diameter[ctroid[layer][u]]; }

void preDfs (int u, int layer) {
    szDfs(u, u);
    int tmp = sz[u], ori = u;

    u = ctroid[layer][u] = centroid(u, u, layer, tmp);
    sztr[u] = tmp, depth[u] = lazyIT(tmp), tree[u] = IT(adj[u].size()), childDiam[u] = IT(adj[u].size());
    timeDfs = 0, calcDfs(u, u, u, layer), del[u] = 1;

    int trsz = adj[u].size() - 1;
    for (int i = 0; i < adj[u].size(); i++) {
        ll v, w; tie(v, w) = adj[u][i];
        if (del[v]) continue;
        preDfs(v, layer + 1);

        ll cur = depth[u].query(in[layer][v], out[layer][v], 1, 1, sztr[u]);
        tree[u].update(child[u].size(), cur, 1, 0, trsz);
        childDiam[u].update(child[u].size(), getDiam(layer + 1, v), 1, 0, trsz);
        child[u].push_back(v);

    }
    diameter[u] = max(childDiam[u].query(0, trsz, 1, 0, trsz).first, twoBest(tree[u], trsz));
    del[u] = 0;
}

void update (int u, int layer, int a, int b, ll incr) {
    int ori = u;
    u = ctroid[layer][u], del[u] = 1;
    if (depth[u].query(in[layer][a], in[layer][a], 1, 1, sztr[u]) >
        depth[u].query(in[layer][b], in[layer][b], 1, 1, sztr[u])) swap(a, b);

    // for this re-rooted subtree, a is parent of b
    depth[u].update(in[layer][b], out[layer][b], incr, 1, 1, sztr[u]);
    int trsz = adj[u].size() - 1;

    function<bool(int,int,int)> range = [&] (int p, int l, int r) {
        return l <= p && p <= r;
    };
    function<bool(int,int)> cmp = [&] (int a, int b) {
        return in[layer][a] < in[layer][b];
    };

    int id = upper_bound(all(child[u]), b, cmp) - child[u].begin() - 1, v = child[u][id];
    ll cur = depth[u].query(in[layer][v], out[layer][v], 1, 1, sztr[u]);
    tree[u].update(id, cur, 1, 0, trsz);
    if (u != a) {
        update(v, layer + 1, a, b, incr);
        childDiam[u].update(id, getDiam(layer + 1, v), 1, 0, trsz);
    }

    diameter[u] = max(childDiam[u].query(0, trsz, 1, 0, trsz).first, twoBest(tree[u], trsz)), del[u] = 0;
}

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

    int n, q; ll w; cin >> n >> q >> w;

    vector<tt> edge;
    for (int i = 1; i < n; i++) {
        int a, b; ll c; cin >> a >> b >> c;
        adj[a].emplace_back(b, c);
        adj[b].emplace_back(a, c);
        edge.emplace_back(a, b, c);
    }
    preDfs(1, 0);

    ll ans = 0;
    while (q--) {
        ll x, y; cin >> x >> y;
        ll d = (ans + x) % (n - 1), e = (ans + y) % w;
        int a, b; ll weight; tie(a, b, weight) = edge[d];

        ll incr = e - weight;
        edge[d] = make_tuple(a, b, e);
        update(1, 0, a, b, incr);

        ans = getDiam(0, 1);
        cout << ans << "\n";
    }

    return 0;
}

Compilation message (stderr)

diameter.cpp: In function 'void calcDfs(int, int, int, int)':
diameter.cpp:85:15: warning: structured bindings only available with '-std=c++17' or '-std=gnu++17'
   85 |     for (auto [v, w] : adj[u]) {
      |               ^
diameter.cpp: In function 'int szDfs(int, int)':
diameter.cpp:95:15: warning: structured bindings only available with '-std=c++17' or '-std=gnu++17'
   95 |     for (auto [v, w] : adj[u])
      |               ^
diameter.cpp: In function 'int centroid(int, int, int, int)':
diameter.cpp:101:15: warning: structured bindings only available with '-std=c++17' or '-std=gnu++17'
  101 |     for (auto [v, w] : adj[u])
      |               ^
diameter.cpp: In function 'void preDfs(int, int)':
diameter.cpp:126:23: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<std::pair<long long int, long long int> >::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  126 |     for (int i = 0; i < adj[u].size(); i++) {
      |                     ~~^~~~~~~~~~~~~~~
diameter.cpp:119:22: warning: unused variable 'ori' [-Wunused-variable]
  119 |     int tmp = sz[u], ori = u;
      |                      ^~~
diameter.cpp: In function 'void update(int, int, int, int, ll)':
diameter.cpp:142:9: warning: unused variable 'ori' [-Wunused-variable]
  142 |     int ori = u;
      |         ^~~
#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...