萌新初学OI求助大ds
查看原帖
萌新初学OI求助大ds
677234
FstAutoMaton楼主2024/7/19 15:25

RT,用的是点分治+虚树上dp的做法,但40分有 WA 有 T,求巨佬把WA改好就行。

code:

#include <bits/stdc++.h>

using namespace std;
using LL = long long;
using Pii = pair<int, int>;

const int kMaxN = 366667, kL = 21;

int dep[kMaxN], f[kL][kMaxN], id[kMaxN << 2], dfn[kMaxN], dp[kMaxN][2], tot, n, m, cnt;  // 基础,虚树
int vis[kMaxN], p[kMaxN << 2], pos[kMaxN], s[kMaxN], fv[kMaxN], sz, rt;                  // 点分治,重心
LL val[kMaxN], dis[kMaxN], dist[kMaxN];                                                  // 在原树上的值,dis:T2,dist:T1
LL c[kMaxN], ans = -1e18;                                                                        // 在虚树上的dis,color,原树上的dis
vector<Pii> g[3][kMaxN];

// Lca begin

void InitLen(int u, int fa) {
  for (Pii i : g[0][u]) {
    if (i.first != fa) {
      dist[i.first] = dist[u] + i.second;
      InitLen(i.first, u);
    }
  }
}

void InitDfs(int u, int fa) {
  dep[u] = dep[fa] + 1, dfn[u] = ++cnt;
  pos[u] = tot + 1;
  for (Pii i : g[1][u]) {
    if (i.first != fa) {
      id[++tot] = u, dis[i.first] = dis[u] + i.second;
      InitDfs(i.first, u);
    }
  }
  id[++tot] = u;
}

int Min(int x, int y) {
  return dep[x] <= dep[y] ? x : y;
}

int Lca(int x, int y) {
  int l = pos[x], r = pos[y];
  (l > r) && (swap(l, r), 1);
  int v = p[r - l + 1];
  return Min(f[v][l], f[v][r - (1 << v) + 1]);
}

void Init() {
  p[0] = -1;
  for (int i = 1; i <= tot; i++) {
    p[i] = p[i >> 1] + 1;
  }
  for (int i = 1; i <= tot; i++) {
    f[0][i] = id[i];
  }
  for (int i = 1; i < kL; i++) {
    for (int j = 1; j + (1 << i) - 1 <= tot; j++) {
      f[i][j] = Min(f[i - 1][j], f[i - 1][j + (1 << i - 1)]);
    }
  }
}

// 虚树begin

bool Cmp(int x, int y) {
  return dfn[x] < dfn[y];
}

LL Dis(int x, int y) {
  int l = Lca(x, y);
  return dis[x] + dis[y] - 2 * dis[l];
}

void Add(int u, int v) {
  if (u != v) {
    g[2][u].push_back({v, 0}), g[2][v].push_back({u, 0});
  }
}

void Build() {
  int v = cnt;
  id[++v] = 1;
  for (int i = 1; i < cnt; i++) {
    id[++v] = Lca(id[i], id[i + 1]);
  }
  cnt = v;
  sort(id + 1, id + cnt + 1, Cmp);
  cnt = unique(id + 1, id + cnt + 1) - id - 1;
  if (cnt == 1) {
    g[2][id[1]].clear();
    dp[id[1]][0] = dp[id[1]][1] = 0;
    return;
  }
  for (int i = 1; i <= cnt; i++) {
    g[2][id[i]].clear(), dp[id[i]][0] = dp[id[i]][1] = 0;
    (i < cnt) && (g[2][Lca(id[i], id[i + 1])].clear(), 1);
  }
  Add(Lca(id[1], id[2]), id[1]);
  for (int i = 1; i < cnt; i++) {
    Add(Lca(id[i], id[i + 1]), id[i + 1]);
  }
}

// dpdp!!!!!!!

bool GetMax(int x, int y) {
  return val[x] > val[y];
}

void Dp(int u, int fa) {
  c[u] && (dp[u][0] = u);
  (c[u] == -1) && (ans = max(ans, val[u] * 2 - dis[u] * 2));
  for (Pii i : g[2][u]) {
    int v = i.first;
    if (v != fa) {
      Dp(v, u);
      for (int j = 0; j < 2; j++) {
        for (int k = 0; k < 2; k++) {
          if (dp[u][j] && dp[v][k] && c[dp[u][j]] != c[dp[v][k]]) {
            // cout << val[dp[u][j]] + val[dp[v][k]] - 2 * dis[u] << " " << dp[u][j] << " " << dis[u] << " " << u << "\n";
            ans = max(ans, val[dp[u][j]] + val[dp[v][k]] - 2 * dis[u]);
          }
        }
      }
      int a[] = {dp[u][0], dp[u][1], dp[v][0], dp[v][1]};
      sort(a, a + 4, GetMax);
      dp[u][0] = a[0];
      for (int i = 1; i < 4; i++) {
        if (c[a[i]] != c[a[0]]) {
          dp[u][1] = a[i];
          break;
        }
      }
    }
  }
}

// 找重心

void FindRt(int u, int fa) {
  fv[u] = 0, s[u] = 1;
  for (Pii i : g[0][u]) {
    if (i.first != fa && !vis[i.first]) {
      FindRt(i.first, u);
      fv[u] = max(fv[u], s[i.first]);
      s[u] += s[i.first];
    }
  }
  fv[u] = max(fv[u], sz - s[u]);
  (fv[u] <= fv[rt]) && (rt = u);
}

// 点分治

void Clear(int u, int fa) {
  c[u] = 0;
  for (Pii i : g[0][u]) {
    if (i.first != fa) {
      Clear(i.first, u);
    }
  }
}

void Dfs(int u, int fa, int col, LL dis) {
  c[u] = col, id[++cnt] = u;
  val[u] = dis + dist[u];
  for (Pii i : g[0][u]) {
    if (i.first != fa && !vis[i.first]) {
      Dfs(i.first, u, col, dis + i.second);
    }
  }
}

void Work(int u) {
  cnt = 0, val[u] = dist[u];
  for (Pii i : g[0][u]) {
    if (!vis[i.first]) {
      Dfs(i.first, u, i.first, i.second);
    }
  }
  id[++cnt] = u, c[u] = -1;
  Build();
  Dp(1, 0);
  // cout << u << " ------------------\n";
  c[u] = 0;
  for (Pii i : g[0][u]) {
    if (!vis[i.first]) {
      Clear(i.first, u);
    }
  }
}

void Solve(int u) {
  vis[u] = 1;
  Work(u);
  for (Pii i : g[0][u]) {
    if (!vis[i.first]) {
      rt = 0, sz = s[i.first];
      FindRt(i.first, u);
      Solve(rt);
    }
  }
}

int main() {
  // freopen("wronganswer7.in", "r", stdin);
  ios ::sync_with_stdio(0), cin.tie(0), cout.tie(0);
  fv[0] = 1e9;
  cin >> n;
  for (int id = 0; id < 2; id++) {
    for (int i = 1, u, v, w; i < n; i++) {
      cin >> u >> v >> w;
      g[id][u].push_back({v, w}), g[id][v].push_back({u, w});
    }
  }
  InitLen(1, 0);
  InitDfs(1, 0);
  Init();
  cnt = 0;
  sz = n, rt = 0;
  FindRt(1, 0);
  Solve(rt);
  cout << ans / 2;
  return 0;
}
2024/7/19 15:25
加载中...