Submission #1093572

#TimeUsernameProblemLanguageResultExecution timeMemory
1093572fryingducDynamic Diameter (CEOI19_diameter)C++17
49 / 100
5061 ms559692 KiB
#include "bits/stdc++.h"
using namespace std;

const int maxn = 1e5 + 5;
const int LG = 17;
int n, q;
int edge_u[maxn], edge_v[maxn];
long long weights[maxn];
int roots[maxn];
vector<pair<int, int>> g[maxn];
bool del[maxn];
int sz[maxn];
vector<int> forest[maxn];
vector<int> contained_in_forest[maxn];
int num_trees;

multiset<long long> res_per_tree;

long long res;

long long encode_w;

struct segment_tree {
  int n;
  vector<long long> tree;
  vector<long long> lazy;
  segment_tree() {}
  segment_tree(int n) : n(n), tree(n * 4 + 6), lazy(n * 4 + 6) {}
  void down(int ind, int l, int r) {
    tree[ind] += lazy[ind];
    if(l != r) {
      lazy[ind << 1] += lazy[ind];
      lazy[ind << 1 | 1] += lazy[ind];
    }
    lazy[ind] = 0;
  }
  void update(int ind, int l, int r, int x, int y, long long val) {
    if(lazy[ind]) down(ind, l, r);
    if(l > y || r < x) return;
    if(x <= l and r <= y) {
      lazy[ind] += val;
      down(ind, l, r);
      return;
    }
    int mid = (l + r) >> 1;
    update(ind << 1, l, mid, x, y, val);
    update(ind << 1 | 1, mid + 1, r, x, y, val);
    tree[ind] = max(tree[ind << 1], tree[ind << 1 | 1]);    
  }
  long long get(int ind, int l, int r, int x, int y) {
    if(lazy[ind]) down(ind, l, r);
    if(l > y || r < x) return 0;
    if(x <= l and r <= y) {
      return tree[ind];
    }
    int mid = (l + r) >> 1;
    return max(get(ind << 1, l, mid, x, y), get(ind << 1 | 1, mid + 1, r, x, y));
  }
  void update(int x, int y, long long val) {
    update(1, 1, n, x, y, val);
  }
  long long get(int x, int y) {
    return get(1, 1, n, x, y);
  }
};
pair<long long, long long> operator+(const pair<long long, long long> &x, const pair<long long, long long> &y) {
  pair<long long, long long> res = x;
  if(y.first > x.first) {
    res.first = y.first;
    res.second = max(x.first, y.second); 
  }
  else if(y.first > x.second) {
    res.second = y.first;
  }
  return res;
}
struct segment_tree_second {
  int n;
  vector<pair<long long, long long>> tree;
  segment_tree_second() {}
  segment_tree_second(int n) : n(n), tree(n * 4 + 6) {}
  void update(int ind, int l, int r, int pos, long long val) {
    if(l == r) {
      tree[ind] = make_pair(val, 0);
      return;
    }
    int mid = (l + r) >> 1;
    if(pos <= mid) update(ind << 1, l, mid, pos, val);
    else update(ind << 1 | 1, mid + 1, r, pos, val);
    tree[ind] = tree[ind << 1] + tree[ind << 1 | 1];
  }
  pair<long long, long long> get(int ind, int l, int r, int x, int y) {
    if(l > y || r < x) return make_pair(0, 0);
    if(x <= l and r <= y) {
      return tree[ind];
    }
    int mid = (l + r) >> 1;
    return get(ind << 1, l, mid, x, y) + get(ind << 1 | 1, mid + 1, r, x, y);
  }
  void update(int pos, long long val) {
    update(1, 1, n, pos, val);
  }
  pair<long long, long long> get(int x, int y) {
    return get(1, 1, n, x, y);
  }
  pair<long long, long long> get() {
    return get(1, 1, n, 1, n);
  }
};
int find_centroid(int u, int prev, int n) {
  for(auto e:g[u]) {
    if(e.first != prev and !del[e.first] and sz[e.first] * 2 > n) 
      return find_centroid(e.first, u, n);
  }
  return u;
}
void re_dfs(int u, int prev) {
  sz[u] = 1;
  for(auto e:g[u]) {
    if(e.first == prev || del[e.first]) continue;
    re_dfs(e.first, u);
    sz[u] += sz[e.first];
  }
}
void collect_tree(int u, int prev) {
  for(auto e:g[u]) {
    int v = e.first;
    if(v == prev || del[v]) continue;
    forest[num_trees].push_back(e.second);
    contained_in_forest[e.second].push_back(num_trees);
    collect_tree(v, u);
  }
}
void decompose(int u, int prev) {
  re_dfs(u, prev);
  int c = find_centroid(u, prev, sz[u]);
  
  ++num_trees;
  roots[num_trees] = c;
  
  for(auto e:g[c]) {
    int v = e.first;
    if(del[v]) continue;
    forest[num_trees].push_back(e.second);
    contained_in_forest[e.second].push_back(num_trees);
    collect_tree(v, c);
  }
  del[c] = 1;
  for(auto e:g[c]) {
    int v = e.first;
    if(v == prev || del[v]) continue;
    decompose(v, c);
  }
}
struct tree {
  int n;
  int root;
  vector<vector<pair<int, long long>>> adj;
  vector<vector<int>> up;
  vector<int> h;
  vector<int> et;
  vector<int> tin, tout;
  vector<long long> max_path;
  vector<int> vertices;
  vector<int> rev;
  segment_tree st;
  segment_tree_second stx;
  int timer;
  vector<int> id;
  tree() {}
  tree(int root) : root(root) {
    vertices.push_back(root);
  }
  void pre_dfs(int u, int prev, long long dep) {
    tin[u] = ++timer;
    et[timer] = u;
    st.update(tin[u], tin[u], dep);
    for(auto e:adj[u]) {
      int v = e.first;
      if(v == prev) continue;
      h[v] = h[u] + 1;
      up[v][0] = u;
      for(int i = 1; i <= LG; ++i) {
        up[v][i] = up[up[v][i - 1]][i - 1];
      }
      pre_dfs(v, u, dep + e.second);
    }
    tout[u] = timer;
  }
  int kth_anc(int u, int k) {
    for(int i = LG; i >= 0; --i) {
      if(k >> i & 1) u = up[u][i];
    }
    return u;
  }
  void resize(int n) {
    adj.resize(n + 1);
    tin.resize(n + 1);
    tout.resize(n + 1);
    id.resize(n + 1);
    et.resize(n + 1);
    h.resize(n + 1);
    rev.resize(n + 1, -1);
    st = segment_tree(n);
    up.resize(n + 1, vector<int>(LG + 1));
    timer = 0;
  }
  void build(vector<int> &vec) {
    for(auto i:vec) {
      vertices.push_back(edge_u[i]);
      vertices.push_back(edge_v[i]);
    }
    sort(vertices.begin(), vertices.end());
    vertices.erase(unique(vertices.begin(), vertices.end()), vertices.end());
    
    n = vertices.size();
    root = lower_bound(vertices.begin(), vertices.end(), root) - vertices.begin() + 1;
    resize(n);
    for(auto i:vec) {
      int u = edge_u[i], v = edge_v[i];
      u = lower_bound(vertices.begin(), vertices.end(), u) - vertices.begin() + 1;
      v = lower_bound(vertices.begin(), vertices.end(), v) - vertices.begin() + 1;
      long long w = weights[i];
      adj[u].emplace_back(v, w);
      adj[v].emplace_back(u, w);
    } 
    pre_dfs(root, 0, 0);
    max_path.resize((int)adj[root].size());
    stx = segment_tree_second((int)adj[root].size());
    for(int i = 0; i < (int)adj[root].size(); ++i) {
      int v = adj[root][i].first;
      max_path[i] = st.get(tin[v], tout[v]);
      rev[v] = i;
      stx.update(i + 1, max_path[i]);
    }
  }
  void update(int u, int v, long long w) {
    u = lower_bound(vertices.begin(), vertices.end(), u) - vertices.begin() + 1;
    v = lower_bound(vertices.begin(), vertices.end(), v) - vertices.begin() + 1;
    
    if(up[u][0] == v) swap(u, v);
    st.update(tin[v], tout[v], w);
    int ancestor = kth_anc(v, h[v] - 1);
    max_path[rev[ancestor]] = st.get(tin[ancestor], tout[ancestor]); 
    stx.update(rev[ancestor] + 1, max_path[rev[ancestor]]);   
  }
  long long get() {
    auto res = stx.get();
    return res.first + res.second;    
  }
} trees[maxn];
void update_forest(int edge_id, long long new_weight) {
  int u = edge_u[edge_id], v = edge_v[edge_id];
  long long last_weight = weights[edge_id];
  for(auto cur_tree: contained_in_forest[edge_id]) {
    long long last_res = trees[cur_tree].get();
    if(res_per_tree.find(last_res) != res_per_tree.end()) {
      res_per_tree.erase(res_per_tree.find(last_res));
    }
    trees[cur_tree].update(u, v, new_weight - last_weight);
    res_per_tree.insert(trees[cur_tree].get());
  }
  weights[edge_id] = new_weight;
}
void solve() {
  cin >> n >> q >> encode_w;
  for(int i = 1; i < n; ++i) {
    int u, v;
    long long w; cin >> u >> v >> w;
    weights[i] = w;
    edge_u[i] = u, edge_v[i] = v;
    g[u].emplace_back(v, i);
    g[v].emplace_back(u, i);
  }
   
  decompose(1, 0);
  for(int i = 1; i <= num_trees; ++i) {
//    cerr << "tree " << roots[i] << " " << i << '\n';
//    for(auto j:forest[i]) cerr << j << " ";
//    cerr << endl;
    trees[i] = tree(roots[i]);
    trees[i].build(forest[i]);
    
    res_per_tree.insert(trees[i].get());
  }
  while(q--) {
    int dj;
    long long ej;
    cin >> dj >> ej;
    dj = (1ll * dj + 1ll * res) % (n - 1) + 1;
    ej = (ej + res) % encode_w;
    
    update_forest(dj, ej);
    
    res = *res_per_tree.rbegin();
    cout << res << '\n';
  }
}
signed main() {
  ios_base::sync_with_stdio(0);
  cin.tie(0);

  solve();
  return 0;
}
/*
10 10 10000
1 9 1241
5 6 1630
10 5 1630
2 6 853
10 1 511
5 3 760
8 3 1076
4 10 1483
7 10 40
8 2051
5 6294
5 4168
7 1861
0 5244
6 5156
3 3001
8 5267
5 3102
8 3623

7 3 0
1 2 6
1 3 2
3 4 2
4 5 2
5 6 5
2 7 1
6 3
3 5
2 4

7 1 0
1 2 6
1 3 2
3 4 2
4 5 2
5 6 5
2 7 1
6 3
*/
#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...