結果
| 問題 |
No.386 貪欲な領主
|
| コンテスト | |
| ユーザー |
zaki_joho
|
| 提出日時 | 2019-03-19 19:49:49 |
| 言語 | C++14 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
AC
|
| 実行時間 | 155 ms / 2,000 ms |
| コード長 | 6,698 bytes |
| コンパイル時間 | 2,017 ms |
| コンパイル使用メモリ | 187,916 KB |
| 実行使用メモリ | 14,720 KB |
| 最終ジャッジ日時 | 2024-09-14 05:10:22 |
| 合計ジャッジ時間 | 4,082 ms |
|
ジャッジサーバーID (参考情報) |
judge2 / judge1 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| other | AC * 16 |
ソースコード
#include "bits/stdc++.h"
using namespace std;
struct RangeSumQuery
{
using type = long long;
static type id() { return 0; }
static type op(const type &l, const type &r) { return l + r; }
};
template <typename M>
class SegmentTree
{
using T = typename M::type;
int n;
std::vector<T> node;
public:
// v を基に初期化
SegmentTree(const std::vector<T> &v)
{
// n は v.size() 以上の最小の2冪
n = 1;
while (n < int(v.size()))
n *= 2;
node.resize(2 * n, M::id());
// i の子 -> 2*i+1, 2*i+2 , 親 -> (i-1)/2
for (int i = 0; i < int(v.size()); i++)
node[i + n] = v[i];
for (int i = n - 1; i >= 0; i--)
node[i] = M::op(node[2 * i], node[2 * i + 1]);
}
// Monoid::id 初期化
SegmentTree(int _n)
{
// n は v.size() 以上の最小の2冪
n = 1;
while (n < _n)
n *= 2;
node.resize(2 * n, M::id());
}
// x 番目を val に更新
void update(int x, T val)
{
x += n;
node[x] = val;
while (x >>= 1)
{
node[x] = M::op(node[2 * x], node[2 * x + 1]);
}
}
// v[x] を M::op(v[x], val) に更新
void operation(int x, T val)
{
x += n;
node[x] = M::op(node[x], val);
while (x >>= 1)
{
node[x] = M::op(node[2 * x], node[2 * x + 1]);
}
}
// [a, b] の op
T query(int l, int r)
{
l += n;
r += n;
T retl = M::id(), retr = M::id();
while (l < r)
{
if (l & 1)
retl = M::op(retl, node[l++]);
if (r & 1)
retr = M::op(node[--r], retr);
l >>= 1;
r >>= 1;
}
return M::op(retl, retr);
}
};
// http://beet-aizu.hatenablog.com/entry/2017/12/12/235950
struct HeavyLightDecomposition
{
int n, pos;
vector<vector<int>> G;
// HL分解後のグラフでのid
vector<int> id;
// 頂点が属するheavy-pathのheavyHeadIdのid
vector<int> heavyHeadId;
// 部分木のサイズ
vector<int> subTreeSize;
// heavy-path上での次の頂点のid
vector<int> heavyNextId;
// 親のid
vector<int> par;
// 深さ
vector<int> dep;
// HL分解前のグラフのid
vector<int> invId;
// 森をHL分解するときの属する木の番号
vector<int> treeId;
HeavyLightDecomposition() {}
HeavyLightDecomposition(int _n) : n(_n), pos(0), G(n),
id(n, -1), heavyHeadId(n), subTreeSize(n, 1), heavyNextId(n, -1),
par(n), dep(n), invId(n), treeId(n) {}
// u, v に無向辺を追加
void add_edge(int u, int v)
{
G[u].push_back(v);
G[v].push_back(u);
}
void build(vector<int> rs = vector<int>(1, 0))
{
int c = 0;
for (int r : rs)
{
dfs(r);
bfs(r, c++);
}
}
void dfs(int rootId)
{
using T = pair<int, int>;
stack<T> st;
par[rootId] = -1;
dep[rootId] = 0;
st.emplace(rootId, 0);
while (!st.empty())
{
int v = st.top().first;
int &i = st.top().second;
if (i < (int)G[v].size())
{
int u = G[v][i++];
if (u == par[v])
continue;
par[u] = v;
dep[u] = dep[v] + 1;
st.emplace(u, 0);
}
else
{
st.pop();
int res = 0;
for (int u : G[v])
{
if (u == par[v])
continue;
subTreeSize[v] += subTreeSize[u];
if (res < subTreeSize[u])
res = subTreeSize[u], heavyNextId[v] = u;
}
}
}
}
void bfs(int r, int c)
{
int &k = pos;
queue<int> q({r});
while (!q.empty())
{
int h = q.front();
q.pop();
for (int i = h; i != -1; i = heavyNextId[i])
{
treeId[i] = c;
id[i] = k++;
invId[id[i]] = i;
heavyHeadId[i] = h;
for (int j : G[i])
if (j != par[i] && j != heavyNextId[i])
q.push(j);
}
}
}
// for_each(verootIdex)
// u, v を結ぶパス上の各頂点に対し...
// [l,r] <- attention!!
void vertexQuery(int u, int v, const function<void(int, int)> &f)
{
while (1)
{
if (id[u] > id[v])
swap(u, v);
f(max(id[heavyHeadId[v]], id[u]), id[v]);
if (heavyHeadId[u] != heavyHeadId[v])
v = par[heavyHeadId[v]];
else
break;
}
}
// for_each(edge)
// u, v を結ぶ各辺に対し...
// [l,r] <- attention!!
void for_each_edge(int u, int v, const function<void(int, int)> &f)
{
while (1)
{
if (id[u] > id[v])
swap(u, v);
if (heavyHeadId[u] != heavyHeadId[v])
{
f(id[heavyHeadId[v]], id[v]);
v = par[heavyHeadId[v]];
}
else
{
if (u != v)
f(id[u] + 1, id[v]);
break;
}
}
}
int lca(int u, int v)
{
while (1)
{
if (id[u] > id[v])
swap(u, v);
if (heavyHeadId[u] == heavyHeadId[v])
return u;
v = par[heavyHeadId[v]];
}
}
int distance(int u, int v)
{
return dep[u] + dep[v] - 2 * dep[lca(u, v)];
}
int getId(int u)
{
return id[u];
}
};
int main()
{
cin.tie(0);
ios::sync_with_stdio(false);
int n;
cin >> n;
SegmentTree<RangeSumQuery> st(n);
HeavyLightDecomposition hl(n);
for (int i = 0; i < n - 1; i++)
{
int a, b;
cin >> a >> b;
hl.add_edge(a, b);
}
hl.build();
for (int i = 0; i < n; i++)
{
int index, u;
cin >> u;
index = hl.getId(i);
st.update(index, u);
}
int m;
cin >> m;
long long ret = 0;
while (m--)
{
long long a, b, c;
cin >> a >> b >> c;
hl.vertexQuery(a, b, [&](int l, int r) { ret += c * st.query(l, r + 1); });
}
cout << ret << endl;
}
zaki_joho