結果
問題 |
No.3113 The farthest point
|
ユーザー |
![]() |
提出日時 | 2025-04-19 18:48:13 |
言語 | C++23 (gcc 13.3.0 + boost 1.87.0) |
結果 |
AC
|
実行時間 | 182 ms / 2,000 ms |
コード長 | 4,727 bytes |
コンパイル時間 | 3,897 ms |
コンパイル使用メモリ | 300,068 KB |
実行使用メモリ | 18,036 KB |
最終ジャッジ日時 | 2025-04-19 18:48:22 |
合計ジャッジ時間 | 7,917 ms |
ジャッジサーバーID (参考情報) |
judge5 / judge4 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
sample | AC * 3 |
other | AC * 33 |
ソースコード
#include <bits/stdc++.h> using namespace std; #define For(i, a, b) for(int i = (a); i < (b); i++) #define rep(i, n) For(i, 0, n) #define rFor(i, a, b) for(int i = (a); i >= (b); i--) #define ALL(v) (v).begin(), (v).end() #define rALL(v) (v).rbegin(), (v).rend() #define SZ(v) ((int)(v).size()) using lint = long long; using ld = long double; int INF = 2000000000; lint LINF = 1000000000000000000; struct SetupIo { SetupIo() { ios::sync_with_stdio(false); cin.tie(nullptr); cout << fixed << setprecision(15); cerr << fixed << setprecision(15); } } setupio; template <class T, T (*op)(T, T), T (*e)()> struct DST { private: int n, h = 1, w; vector<vector<T>> table; vector<int> get; public: DST() {} DST(vector<T> &v) : n(v.size()) { while ((1 << h) < n) { h++; } int w = (1 << h); table.assign(h, vector<T>(w, e())); for (int i = 0; i < h; i++) { int len = (1 << (h - i - 1)); for (int pos = (1 << (h - i - 1)) - 1; pos < w; pos += (len << 1)) { for (int j = pos; j >= pos - len + 1; j--) { table[i][j] = (j == pos ? v[j] : op(v[j], table[i][j + 1])); } for (int j = pos + 1; j <= pos + len; j++) { table[i][j] = (j == pos + 1 ? v[j] : op(table[i][j - 1], v[j])); } } } get.resize(w); for (int i = 1; i < w; i++) { get[i] = __builtin_clz(i) - (32 - h); } } T prod(int l, int r) const { assert(0 <= l && l <= r && r <= n); if (l == r) { return e(); } if (r - l == 1) { return table[h - 1][l]; } int i = get[l ^ (r - 1)]; return op(table[i][l], table[i][r - 1]); } }; lint op(lint a, lint b) { return max(a, b); } lint e() { return 0; } int main() { int n; cin >> n; vector<vector<pair<int, lint>>> g(n); rep(i, n - 1) { int u, v, w; cin >> u >> v >> w; u--, v--; g[u].emplace_back(v, w); g[v].emplace_back(u, w); } // v の部分木について, // 「葉 ~ v パスの長さの最大値 path(v)」と // 「v の部分木の任意の 2 頂点間の単純パスの重みの和の最大値 real(v)」 // のペアを返す auto dfs = [&](auto dfs, int v, int pv) -> pair<lint, lint> { lint path = 0, real = 0; vector<lint> costs, paths, reals; for (auto [nv, w] : g[v]) { if (nv == pv) { continue; } auto [x, y] = dfs(dfs, nv, v); costs.emplace_back(w); paths.emplace_back(x); reals.emplace_back(y); } // 葉 ~ v パスの長さの最大値としてありえるもの // 1. v だけ(長さ 0 のパス) // 2. v -> nv パス(cost(v, nv)) // 3. 葉 ~ nv -> v パス(path(nv) + cost(nv, v)) // 2 if (SZ(costs) >= 1) { path = max(path, *max_element(ALL(costs))); } // 3 rep(i, SZ(paths)) { path = max(path, paths[i] + costs[i]); } // v の部分木についての最大値としてありえるもの // 上の 1 ~ 3 // 4. nv の部分木についての最大値(real(nv)) // 5. nv1 -> v -> nv2 パス(cost(nv1, v) + cost(v, nv2)) // 6. 葉 ~ nv1 -> v -> nv2 パス(path(nv1) + cost(nv1, v) + cost(v, nv2)) // 7. 葉 ~ nv1 -> v -> nv2 ~ 葉 パス(path(nv1) + cost(nv1, v) + cost(v, nv2) + path(nv2)) // 1 ~ 3 real = max(real, path); // 4 if (SZ(reals) >= 1) { real = max(real, *max_element(ALL(reals))); } if (SZ(costs) >= 2) { // 5 auto costs2 = costs; sort(rALL(costs2)); real = max(real, costs[0] + costs[1]); // 6 vector<lint> sums; rep(i, SZ(paths)) { sums.emplace_back(costs[i] + paths[i]); } DST<lint, op, e> Costs(costs); rep(i, SZ(paths)) { lint tmp = sums[i]; tmp += max(Costs.prod(0, i), Costs.prod(i + 1, SZ(costs))); real = max(real, tmp); } // 7 DST<lint, op, e> Sums(sums); rep(i, SZ(sums)) { lint tmp = sums[i]; tmp += max(Sums.prod(0, i), Sums.prod(i + 1, SZ(sums))); real = max(real, tmp); } } return {path, real}; }; cout << dfs(dfs, 0, -1).second << "\n"; }