Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

weight LCA dist #104

Open
wants to merge 8 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions .verify-helper/timestamps.remote.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"test/aoj-3314.test.cpp": "2023-10-12 08:50:40 +0900",
"test/aoj-3372.test.cpp": "2024-10-05 23:18:48 +0900",
"test/aoj-alds1-3-c.test.py": "2023-09-05 02:43:56 +0900",
"test/aoj-cgl-2-b.test.cpp": "2023-09-07 23:01:33 +0900",
"test/aoj-cgl-2-c.test.cpp": "2023-09-07 23:01:33 +0900",
Expand All @@ -16,8 +17,8 @@
"test/aoj-dsl-2-g.test.cpp": "2023-08-01 17:59:54 +0900",
"test/aoj-dsl-2-h.test.cpp": "2023-08-01 17:59:54 +0900",
"test/aoj-dsl-2-i.test.cpp": "2023-08-01 17:59:54 +0900",
"test/aoj-grl-5-a.test.cpp": "2023-06-16 15:41:49 +0900",
"test/aoj-grl-5-b.test.cpp": "2023-06-16 15:41:49 +0900",
"test/aoj-grl-5-a.test.cpp": "2024-10-05 23:18:48 +0900",
"test/aoj-grl-5-b.test.cpp": "2024-10-05 23:18:48 +0900",
"test/atcoder-abc177-f.1.test.cpp": "2023-08-01 17:59:54 +0900",
"test/atcoder-abc177-f.2.test.cpp": "2023-08-01 17:59:54 +0900",
"test/atcoder-abc282-d.test.cpp": "2023-11-30 23:29:28 +0900",
Expand All @@ -32,8 +33,8 @@
"test/yosupo-enumerate-palindromes.test.cpp": "2023-05-31 16:27:00 +0900",
"test/yosupo-enumerate-quotients.test.cpp": "2023-05-03 12:22:21 +0900",
"test/yosupo-enumerate-quotients.test.py": "2023-05-23 13:25:17 +0900",
"test/yosupo-lca.1.test.cpp": "2023-06-16 15:41:49 +0900",
"test/yosupo-lca.2.test.cpp": "2023-08-01 18:34:30 +0900",
"test/yosupo-lca.1.test.cpp": "2024-10-05 23:18:48 +0900",
"test/yosupo-lca.2.test.cpp": "2024-10-05 23:18:48 +0900",
"test/yosupo-line-add-get-min.test.cpp": "2023-06-19 07:11:52 +0900",
"test/yosupo-point-add-rectangle-sum.test.cpp": "2023-06-25 14:14:02 +0900",
"test/yosupo-point-set-range-composite.1.test.cpp": "2023-08-29 23:08:45 +0900",
Expand All @@ -53,6 +54,7 @@
"test/yukicoder-186.test.cpp": "2023-09-16 00:07:15 +0900",
"test/yukicoder-187.test.cpp": "2023-09-16 00:07:15 +0900",
"test/yukicoder-2292.test.cpp": "2023-08-01 17:59:54 +0900",
"test/yukicoder-898.test.cpp": "2024-10-05 23:18:48 +0900",
"test/yukicoder-rotate-enlarge_1.test.cpp": "2023-10-12 08:50:40 +0900",
"test/yukicoder-rotate-enlarge_2.test.cpp": "2023-10-12 08:50:40 +0900",
"test/yukicoder-search-oji.test.cpp": "2023-10-12 08:50:40 +0900"
Expand Down
1 change: 1 addition & 0 deletions compile_flags.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
-std=gnu++20
48 changes: 41 additions & 7 deletions cpp/tree.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -135,13 +135,14 @@ struct RootedTree : private Tree<Cost> {
using Tree<Cost>::operator[];
using Tree<Cost>::edges;
using Tree<Cost>::shortest_path;
using Tree<Cost>::Tree;

int root; //!< 根
std::vector<Edge> par; //!< 親へ向かう辺
std::vector<std::vector<Edge>> child; //!< 子へ向かう辺のリスト
std::vector<Cost> depth; //!< 深さのリスト
std::vector<Cost> height; //!< 部分木の高さのリスト
std::vector<int> unweighted_depth; //!< 重みなしの深さのリスト
std::vector<int> unweighted_height; //!< 重みなしの部分木の高さのリスト
std::vector<int> sz; //!< 部分期の頂点数のリスト
std::vector<int> preorder; //!< 先行順巡回
std::vector<int> postorder; //!< 後行順巡回
Expand Down Expand Up @@ -207,7 +208,9 @@ struct RootedTree : private Tree<Cost> {
par[root] = {root, -1, 0, -1};
child.resize(n);
depth.resize(n);
unweighted_depth.resize(n);
height.resize(n);
unweighted_height.resize(n);
sz.resize(n);
std::vector<int> iter(n);
std::stack<std::pair<int, int>> stk;
Expand All @@ -221,17 +224,22 @@ struct RootedTree : private Tree<Cost> {
postorder.push_back(u);
sz[u] = 1;
height[u] = 0;
unweighted_height[u] = 0;
for(auto& e : child[u]) {
sz[u] += sz[e.dst];
if(height[u] < height[e.dst] + e.cost) {
height[u] = height[e.dst] + e.cost;
}
if(unweighted_height[u] < unweighted_height[e.dst] + 1) {
unweighted_height[u] = unweighted_height[e.dst] + 1;
}
}
} else {
auto& e = this->g[u][iter[u]++];
par[e.dst] = {e.dst, u, e.cost, e.id};
child[u].push_back(e);
depth[e.dst] = depth[u] + e.cost;
unweighted_depth[e.dst] = unweighted_depth[u] + 1;
stk.emplace(u, cnt + 1);
stk.emplace(e.dst, 0);
}
Expand All @@ -253,7 +261,6 @@ struct DoublingClimbTree : private RootedTree<Cost> {
using RootedTree<Cost>::operator[];
using RootedTree<Cost>::edges;
using RootedTree<Cost>::shortest_path;
using RootedTree<Cost>::RootedTree;
using RootedTree<Cost>::root;
using RootedTree<Cost>::par;
using RootedTree<Cost>::child;
Expand Down Expand Up @@ -287,6 +294,34 @@ struct DoublingClimbTree : private RootedTree<Cost> {
build();
}

/**
* @brief 親の頂点のリストから根が0のダブリング済み根付き木を構築するコンストラクタ
*
* @param par_ 頂点0以外の親の頂点のリスト
* @param padding = -1 parの頂点番号をいくつずらすか
*/
DoublingClimbTree(const std::vector<int>& par_, int padding = -1) : RootedTree<Cost>(par_, padding) {
build();
}
/**
* @brief Treeからダブリング済み根付き木を構築するコンストラクタ(コピー)
*
* @param tree Tree
* @param root 根
*/
DoublingClimbTree(const Tree<Cost>& tree, int root) : RootedTree<Cost>(tree, root) {
build();
}
/**
* @brief Treeからダブリング済み根付き木を構築するコンストラクタ(ムーブ)
*
* @param tree Tree
* @param root 根
*/
DoublingClimbTree(Tree<Cost>&& tree, int root) : RootedTree<Cost>(std::move(tree), root) {
build();
}

/**
* @brief 頂点uからk回を根の方向に遡った頂点
*
Expand All @@ -310,9 +345,8 @@ struct DoublingClimbTree : private RootedTree<Cost> {
* @return int LCAの頂点番号
*/
int lca(int u, int v) const {
if(this->depth[u] > this->depth[v]) std::swap(u, v);
v = climb(v, this->depth[v] - this->depth[u]);
if(this->depth[u] > this->depth[v]) u = climb(u, this->depth[u] - this->depth[v]);
if(this->unweighted_depth[u] > this->unweighted_depth[v]) std::swap(u, v);
v = climb(v, this->unweighted_depth[v] - this->unweighted_depth[u]);
if(u == v) return u;
for(int i = h - 1; i >= 0; i--) {
int nu = doubling_par[i][u];
Expand All @@ -333,14 +367,14 @@ struct DoublingClimbTree : private RootedTree<Cost> {
* @param v 頂点2
* @return int uとv間の最短経路の辺の本数
*/
int dist(int u, int v) const {
Cost dist(int u, int v) const {
return this->depth[u] + this->depth[v] - this->depth[lca(u, v)] * 2;
}

private:
void build() {
int n = this->n;
h = 0;
h = 1;
while((1 << h) < n) h++;
doubling_par.assign(h, std::vector<int>(n, -1));
for(int i = 0; i < n; i++) doubling_par[0][i] = this->par[i];
Expand Down
44 changes: 44 additions & 0 deletions test/aoj-3372.test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
#define PROBLEM "https://onlinejudge.u-aizu.ac.jp/problems/3372"
#include "../cpp/tree.hpp"
using namespace std;
using ll = long long;

template <typename T, typename U>
inline bool chmax(T& x, const U& y) { return x < y ? (x = y, true) : false; }

int main() {
int n; cin >> n;
Tree tr(n); tr.read();
vector<ll> a(n);
for(int i = 0; i < n; i++) cin >> a[i];
auto rt = tr.set_root(0);
Tree<ll> tr_costed(n);
for(int u = 0; u < n; u++) {
for(int v : rt.child[u]) {
tr_costed.add_edge(u, v, a[v]);
}
}
auto lcart = tr_costed.build_lca(0);
vector<int> b(n-1);
vector<int> b_cnt(n);
for(int i = 0; i < n-1; i++) {
cin >> b[i]; b[i]--;
b_cnt[b[i]]++;
}
reverse(b.begin(), b.end());
int init = -1;
for(int i = 0; i < n; i++) {
if(!b_cnt[i]) init = i;
}
tuple<ll, int, int> farthest = {a[init], init, init};
vector<ll> ans = {a[init]};
auto dist = [&](int i, int j) { return lcart.dist(i, j) + a[lcart.lca(i, j)]; };
for(int bi : b) {
auto [d, x, y] = farthest;
chmax(farthest, make_tuple(dist(x, bi), x, bi));
chmax(farthest, make_tuple(dist(y, bi), y, bi));
ans.push_back(get<0>(farthest));
}
reverse(ans.begin(), ans.end());
for(ll a : ans) { cout << a << endl; }
}
22 changes: 22 additions & 0 deletions test/yukicoder-898.test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#define PROBLEM "https://yukicoder.me/problems/no/898"

#include "../cpp/tree.hpp"
#include <bits/stdc++.h>
using namespace std;
using ll = long long;

int main() {
int n; cin >> n;
Tree<ll> tr(n); tr.read(0, true);
DoublingClimbTree<ll> dct(tr, 0);
int q; cin >> q;
while(q--) {
array<int, 3> xyz;
for(int i = 0; i < 3; i++) cin >> xyz[i];
int lca01 = dct.lca(xyz[0], xyz[1]);
int lca02 = dct.lca(xyz[0], xyz[2]);
int lca12 = dct.lca(xyz[1], xyz[2]);
int center = lca01 ^ lca02 ^ lca12;
cout << dct.dist(xyz[0], center) + dct.dist(xyz[1], center) + dct.dist(xyz[2], center) << endl;
}
}
Loading