Submission #529997

#TimeUsernameProblemLanguageResultExecution timeMemory
529997cig32Election Campaign (JOI15_election_campaign)C++17
100 / 100
249 ms71456 KiB
#include "bits/stdc++.h"
using namespace std;
mt19937_64 rng((int)std::chrono::steady_clock::now().time_since_epoch().count());
const int MAXN = 1e5 + 10;
const int MOD = 1e9 + 7;
//#define int long long
 
int rnd(int x, int y) {
  int u = uniform_int_distribution<int>(x, y)(rng); return u;
}
vector<int> adj[MAXN];
int n, m;
vector<int> e;
int dep[MAXN];
int par[17][MAXN];
int pos[MAXN];
int sz[MAXN];
int nxt = 0;
void tour(int node, int prv) {
  e.push_back(node);
  dep[node] = (prv == -1 ? 0 : dep[prv] + 1);
  par[0][node] = prv;
  pos[node] = ++nxt;
  sz[node] = 1;
  for(int x: adj[node]) {
    if(x != prv) {
      tour(x, node);
      sz[node] += sz[x];
      e.push_back(node);
    }
  }
}
int l[MAXN], r[MAXN];
pair<int, int> sp[18][2*MAXN]; 
int lca_idx(int x, int y) {
  int m1 = min(l[x], l[y]);
  int m2 = max(r[x], r[y]);
  int k = 32 - __builtin_clz(m2 - m1 + 1) - 1;
  return min(sp[k][m1], sp[k][m2 - (1<<k) + 1]).second;
}
struct plan {
  int u, v, cost;
};
vector<plan> v[MAXN];
struct node {
  int upd = 0;
  int ans = 0;
} st[4*MAXN];
void u(int l, int r, int constl, int constr, int idx, int val) {
  if(l <= constl && constr <= r) {
    st[idx].upd += val;
    st[idx].ans += val;
    return;
  }
  if(st[idx].upd != 0) {
    st[2*idx+1].upd += st[idx].upd;
    st[2*idx+2].upd += st[idx].upd;
    st[2*idx+1].ans += st[idx].upd;
    st[2*idx+2].ans += st[idx].upd;
    st[idx].upd = 0;
    st[idx].ans = min(st[2*idx+1].ans, st[2*idx+2].ans);
  }
  int mid = (constl + constr) >> 1;
  if(mid < l || r < constl) u(l, r, mid+1, constr, 2*idx+2, val);
  else if(constr < l || r < mid + 1) u(l, r, constl, mid, 2*idx+1, val);
  else {
    u(l, r, constl, mid, 2*idx+1, val);
    u(l, r, mid+1, constr, 2*idx+2, val);
  }
  st[idx].ans = min(st[2*idx+1].ans, st[2*idx+2].ans);
}
int qu(int l, int r, int constl, int constr, int idx) {
  if(l <= constl && constr <= r) return st[idx].ans;
  if(st[idx].upd != 0) {
    st[2*idx+1].upd += st[idx].upd;
    st[2*idx+2].upd += st[idx].upd;
    st[2*idx+1].ans += st[idx].upd;
    st[2*idx+2].ans += st[idx].upd;
    st[idx].upd = 0;
    st[idx].ans = min(st[2*idx+1].ans, st[2*idx+2].ans);
  }
  int mid = (constl + constr) >> 1;
  if(mid < l || r < constl) return qu(l, r, mid+1, constr, 2*idx+2);
  else if(constr < l || r < mid+1) return qu(l, r, constl, mid, 2*idx+1);
  else return min(qu(l, r, constl, mid, 2*idx+1), qu(l, r, mid+1, constr, 2*idx+2));
}
void update(int l, int r, int v) {
  u(l, r, 0, MAXN-1, 0, v);
}
int query(int i) {
  return qu(pos[i], pos[i], 0, MAXN-1, 0);
}
int dpf(int node, int prv) {
  int sum = 0;
  unordered_map<int, int> contrib;
  for(int x: adj[node]) {
    if(x != prv) {
      int d = dpf(x, node);
      sum += d;
      contrib[x] = d;
    }
  }
  int ans = sum;
  if(v[node].size()) {
    for(plan f: v[node]) {
      if(f.u == node || f.v == node) {
        int dist = dep[(f.v == node ? f.u : f.v)] - dep[node] - 1;
        int cur = (f.u == node ? f.v : f.u);
        for(int k=16; k>=0; k--) {
          if(dist >= (1 << k)) {
            dist -= (1 << k);
            cur = par[k][cur];
          }
        }
        ans = max(ans, f.cost + sum - contrib[cur] + query(f.u ^ f.v ^ node));
      }
      else {
        int dist = dep[f.u] - dep[node] - 1;
        int cur = f.u;
        for(int k=16; k>=0; k--) {
          if(dist >= (1 << k)) {
            dist -= (1 << k);
            cur = par[k][cur];
          }
        }
        int dist2 = dep[f.v] - dep[node] - 1;
        int cur2 = f.v;
        for(int k=16; k>=0; k--) {
          if(dist2 >= (1 << k)) {
            dist2 -= (1 << k);
            cur2 = par[k][cur2];
          }
        }
        ans = max(ans, f.cost + sum - contrib[cur] - contrib[cur2] + query(f.u) + query(f.v));
      }
    }
  }
  for(int x: adj[node]) {
    if(x != prv) {
      update(pos[x], pos[x] + sz[x] - 1, sum - contrib[x]);
    }
  }
  update(pos[node], pos[node], sum);
  return ans;
}
void solve(int tc) {
  cin >> n;
  for(int i=1; i<n; i++) {
    int a, b;
    cin >> a >> b;
    adj[a].push_back(b);
    adj[b].push_back(a);
  }
  e.push_back(0);
  tour(1, -1);
  for(int i=1; i<e.size(); i++) {
    if(l[e[i]] == 0) l[e[i]] = i;
    r[e[i]] = i;
  }
  for(int i=1; i<e.size(); i++) sp[0][i] = {dep[e[i]], e[i]};
  for(int i=1; i<18; i++) {
    for(int j=1; j<e.size(); j++) {
      sp[i][j] = min(sp[i-1][j], sp[i-1][j + (1<< (i-1))]);
    }
  }
  for(int i=1; i<17; i++) {
    for(int j=1; j<=n; j++) {
      par[i][j] = par[i-1][par[i-1][j]];
    }
  }
  cin >> m;
  for(int i=1; i<=m; i++) {
    int q, w, z;
    cin >> q >> w >> z;
    int j = lca_idx(q, w);
    v[j].push_back({q, w, z});
  }
  cout << dpf(1, -1) << "\n";
}
int32_t main(){
  ios::sync_with_stdio(0); cin.tie(0);
  int t = 1;// cin >> t;
  for(int i=1; i<=t; i++) solve(i);
}
/*
23
1 2
1 3
1 4
1 5
2 9
2 10
4 19
4 6
5 17
5 18
9 11
10 13
10 16
19 20
6 7
11 12
11 14
11 15
7 8
14 21
14 22
22 23
5
12 3 1
21 23 2
17 18 4
13 16 8
20 8 16
*/

Compilation message (stderr)

election_campaign.cpp: In function 'void solve(int)':
election_campaign.cpp:156:17: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  156 |   for(int i=1; i<e.size(); i++) {
      |                ~^~~~~~~~~
election_campaign.cpp:160:17: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  160 |   for(int i=1; i<e.size(); i++) sp[0][i] = {dep[e[i]], e[i]};
      |                ~^~~~~~~~~
election_campaign.cpp:162:19: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  162 |     for(int j=1; j<e.size(); j++) {
      |                  ~^~~~~~~~~
#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...