結果
| 問題 |
No.399 動的な領主
|
| コンテスト | |
| ユーザー |
risujiroh
|
| 提出日時 | 2019-03-27 05:14:37 |
| 言語 | C++14 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
AC
|
| 実行時間 | 230 ms / 2,000 ms |
| コード長 | 2,779 bytes |
| コンパイル時間 | 2,048 ms |
| コンパイル使用メモリ | 181,240 KB |
| 実行使用メモリ | 22,784 KB |
| 最終ジャッジ日時 | 2024-10-11 01:44:03 |
| 合計ジャッジ時間 | 5,130 ms |
|
ジャッジサーバーID (参考情報) |
judge1 / judge3 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| other | AC * 19 |
ソースコード
#include <bits/stdc++.h>
using namespace std;
using lint = long long;
template<class T = int> using V = vector<T>;
template<class T = int> using VV = V< V<T> >;
template<class T> struct FenwickTree {
const int n;
V<T> t;
FenwickTree(int n) : n(n), t(n + 1) {}
void add(int i, T x) { for (++i; i <= n; i += i & -i) t[i] += x; }
T sum(int i) const {
T s = 0;
for (; i; i -= i & -i) s += t[i];
return s;
}
};
template<class T> struct AddSumTree {
const int n;
FenwickTree<T> d, e;
AddSumTree(int n) : n(n), d(n), e(n) {}
void add(int l, int r, T x) {
d.add(l, x), e.add(l, l * x);
if (r < n) d.add(r, -x), e.add(r, -r * x);
}
T sum(int i) const { return i * d.sum(i) - e.sum(i); }
T sum(int l, int r) const { return sum(r) - sum(l); }
};
using Tree = AddSumTree<uint64_t>;
struct HeavyLightDecomposition {
const bool edge;
const int n;
VV<> g;
V<> sz, par, in, out, anc, rev;
HeavyLightDecomposition(VV<>& g, bool edge, int r = 0) :
edge(edge), n(g.size()), g(g), sz(n), par(n), in(n), out(n), anc(n), rev(n) {
dfs_sz(r, -1);
anc[r] = r;
dfs_hl(r);
}
void dfs_sz(int v, int p) {
par[v] = p;
for (auto&& w : g[v]) if (w == p) {
swap(w, g[v].back());
g[v].pop_back();
break;
}
sz[v] = 1;
for (auto&& w : g[v]) {
dfs_sz(w, v);
sz[v] += sz[w];
if (sz[w] > sz[g[v][0]]) swap(w, g[v][0]);
}
}
void dfs_hl(int v) {
static int t = 0;
in[v] = t++;
rev[in[v]] = v;
for (int w : g[v]) {
anc[w] = w == g[v][0] ? anc[v] : w;
dfs_hl(w);
}
out[v] = t;
}
int lca(int u, int v) const {
while (true) {
if (in[u] > in[v]) swap(u, v);
if (anc[u] == anc[v]) return u;
v = par[anc[v]];
}
}
lint acc(Tree& t, int u, int v) const {
lint res = 0;
while (true) {
if (in[u] > in[v]) swap(u, v);
if (anc[u] == anc[v]) break;
res += t.sum(in[anc[v]], in[v] + 1);
v = par[anc[v]];
}
res += t.sum(in[u] + edge, in[v] + 1);
return res;
}
void act(Tree& t, int u, int v, int f) const {
while (true) {
if (in[u] > in[v]) swap(u, v);
if (anc[u] == anc[v]) break;
t.add(in[anc[v]], in[v] + 1, f);
v = par[anc[v]];
}
t.add(in[u] + edge, in[v] + 1, f);
}
};
int main() {
cin.tie(nullptr); ios::sync_with_stdio(false);
int n; cin >> n;
VV<> g(n);
for (int i = 0; i < n - 1; ++i) {
int u, v; cin >> u >> v, --u, --v;
g[u].push_back(v);
g[v].push_back(u);
}
HeavyLightDecomposition hld(g, false);
Tree t(n);
t.add(0, n, 1);
int q; cin >> q;
lint res = 0;
while (q--) {
int u, v; cin >> u >> v, --u, --v;
res += hld.acc(t, u, v);
hld.act(t, u, v, 1);
}
cout << res << '\n';
}
risujiroh