結果
| 問題 |
No.399 動的な領主
|
| コンテスト | |
| ユーザー |
kcvlex
|
| 提出日時 | 2019-12-06 20:45:02 |
| 言語 | C++14 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
WA
|
| 実行時間 | - |
| コード長 | 7,748 bytes |
| コンパイル時間 | 2,874 ms |
| コンパイル使用メモリ | 192,732 KB |
| 実行使用メモリ | 30,720 KB |
| 最終ジャッジ日時 | 2024-12-23 17:35:57 |
| 合計ジャッジ時間 | 25,427 ms |
|
ジャッジサーバーID (参考情報) |
judge1 / judge5 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| other | AC * 4 WA * 9 TLE * 6 |
ソースコード
#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
#define ALL(V) (V).begin(), (V).end()
#define ALLR(V) (V).rbegin(), (V).rend()
template <typename T> using V = vector<T>;
template <typename T> using VV = V<V<T>>;
using ll = int64_t;
using ull = uint64_t;
using PLL = pair<ll, ll>;
template <typename T> const T& var_min(const T &t) { return t; }
template <typename T> const T& var_max(const T &t) { return t; }
template <typename T, typename... Tail> const T& var_min(const T &t, const Tail&... tail) { return min(t, var_min(tail...)); }
template <typename T, typename... Tail> const T& var_max(const T &t, const Tail&... tail) { return max(t, var_max(tail...)); }
template <typename T, typename... Tail> void chmin(T &t, const Tail&... tail) { t = var_min(t, tail...); }
template <typename T, typename... Tail> void chmax(T &t, const Tail&... tail) { t = var_max(t, tail...); }
template <typename T> const T& clamp(const T &t, const T &low, const T &high) { return max(low, min(high, t)); }
template <typename T> void chclamp(T &t, const T &low, const T &high) { t = clamp(t, low, high); }
namespace init__ {
struct InitIO {
InitIO() {
cin.tie(nullptr);
ios_base::sync_with_stdio(false);
cout << fixed << setprecision(30);
}
} init_io;
}
// #include "lazysegmenttree.cpp"
template <typename T, typename L> struct LazySegmentTree {
using Merge = function<T(T, T)>;
using Apply = function<T(T, L)>;
using Update = function<L(L, L)>;
using GenLazy = function<L(ssize_t, ssize_t, L)>;
using Propagate = function<L(L)>;
ssize_t upper;
T init_node;
L init_lazy;
V<T> node;
V<L> lazy;
V<bool> lazyf;
Merge merge;
Apply apply;
Update update;
GenLazy gen_lazy;
Propagate prop;
public:
LazySegmentTree(
const V<T> &init_v, T init_node, L init_lazy, Merge merge, Apply apply,
Update update, GenLazy gen_lazy, Propagate prop = [](L l) { return l; })
: init_node(init_node), init_lazy(init_lazy), merge(merge), apply(apply),
update(update), gen_lazy(gen_lazy), prop(prop) {
{
upper = 1;
while (upper < init_v.size())
upper *= 2;
}
node.resize(2 * upper - 1, init_node);
lazy.resize(2 * upper - 1, init_lazy);
lazyf.resize(2 * upper - 1, false);
for (ll i = 0; i < init_v.size(); i++)
node[i + upper - 1] = init_v[i];
for (ll i = upper - 2; 0 <= i; i--) {
ll c0, c1;
tie(c0, c1) = get_child_idx(i);
node[i] = merge(node[c0], node[c1]);
}
}
PLL get_child_idx(ll pos) { return PLL(2 * pos + 1, 2 * pos + 2); }
void push(ll pos, ll nl, ll nr) {
if (!lazyf[pos])
return;
node[pos] = apply(node[pos], lazy[pos]);
if (nr - nl > 1) {
ll cidx[2];
tie(cidx[0], cidx[1]) = get_child_idx(pos);
for (ll i = 0; i <= 1; i++) {
lazy[cidx[i]] = update(lazy[cidx[i]], prop(lazy[pos]));
lazyf[cidx[i]] = true;
}
}
lazyf[pos] = false;
lazy[pos] = init_lazy;
}
T update_query(ll ql, ll qr, L val, ll pos, ll nl, ll nr) {
push(pos, nl, nr);
if (qr <= nl || nr <= ql)
return init_node;
if (ql <= nl && nr <= qr) {
lazy[pos] = gen_lazy(nl, nr, val);
lazyf[pos] = true;
push(pos, nl, nr);
return node[pos];
} else {
ll mid = (nl + nr) / 2;
ll c0, c1;
tie(c0, c1) = get_child_idx(pos);
auto lv = update_query(ql, qr, val, c0, nl, mid);
auto rv = update_query(ql, qr, val, c1, mid, nr);
return node[pos] = merge(node[c0], node[c1]);
}
}
T update_query(ll ql, ll qr, L val) {
return update_query(ql, qr, val, 0, 0, upper);
}
T get_query(ll ql, ll qr, ll pos, ll nl, ll nr) {
push(pos, nl, nr);
if (nr <= ql || qr <= nl)
return init_node;
if (ql <= nl && nr <= qr)
return node[pos];
ll mid = (nl + nr) / 2;
ll c0, c1;
tie(c0, c1) = get_child_idx(pos);
auto lv = get_query(ql, qr, c0, nl, mid);
auto rv = get_query(ql, qr, c1, mid, nr);
return merge(lv, rv);
}
T get_query(ll ql, ll qr) { return get_query(ql, qr, 0, 0, upper); }
};
struct HLD {
V<ll> p_node, head_node, hld_id, heavy , tree_size;
HLD(const VV<ll> &edges) : p_node(edges.size()), head_node(edges.size()),
hld_id(edges.size()), heavy(edges.size(), -1),
tree_size(edges.size())
{
calc_size(0, -1, edges);
ll id = 0;
calc_id(0, -1, edges, id);
}
ll calc_size(ll cur, ll pre, const VV<ll> &edges) {
ll ret = 1;
p_node[cur] = pre;
for(ll nxt : edges[cur]) if(nxt != pre) {
ret += calc_size(nxt, cur, edges);
if(heavy[cur] == -1 ||
tree_size[heavy[cur]] < tree_size[nxt]) {
heavy[cur] = nxt;
}
}
return tree_size[cur] = ret;
}
void calc_id(ll cur, ll pre, const VV<ll> &edges, ll &id) {
if(cur == -1) return;
hld_id[cur] = id++;
if(pre == -1) head_node[cur] = cur;
else head_node[cur] = (heavy[pre] == cur ? head_node[pre] : cur);
calc_id(heavy[cur], cur, edges, id);
for(ll nxt : edges[cur]) {
if(nxt == pre || nxt == heavy[cur]) continue;
calc_id(nxt, cur, edges, id);
}
}
ll head_id(ll node) { return hld_id[head_node[node]]; }
ll lca(ll n1, ll n2) {
while(true) {
if(hld_id[n2] < hld_id[n1]) swap(n1, n2);
if(head_node[n1] == head_node[n2]) break;
n2 = p_node[head_node[n2]];
}
return n1;
}
// calc's arg is [l, r)
template <typename T>
T query(ll n1, ll n2, function<T(ll, ll)> calc,
T id_ele, function<T(T, T)> merge)
{
T lval = id_ele, rval = id_ele;
T res = id_ele;
while(true) {
if(head_node[n1] != head_node[n2]) {
if(hld_id[n1] < hld_id[n2]) {
auto tmp = calc(head_id(n2), hld_id[n2] + 1);
rval = merge(tmp, rval);
n2 = p_node[n2];
} else {
auto tmp = calc(head_id(n1), hld_id[n1] + 1);
lval = merge(lval, tmp);
n1 = p_node[n1];
}
} else {
ll id1 = hld_id[n1];
ll id2 = hld_id[n2];
if(id2 < id1) swap(id1, id2);
res = calc(id1, id2 + 1);
res = merge(lval, merge(res, rval));
break;
}
}
return res;
}
};
int main() {
ll N;
cin >> N;
VV<ll> edges(N);
for(ll i = 1; i < N; i++) {
ll a, b;
cin >> a >> b;
a--; b--;
edges[a].push_back(b);
edges[b].push_back(a);
}
HLD hld(edges);
LazySegmentTree<ll, ll> lst(V<ll>(N, 1), 0, 0,
[](ll a, ll b) { return a + b; },
[](ll a, ll b) { return a + b; },
[](ll a, ll b) { return a + b; },
[](ssize_t l, ssize_t r, ll v) { return (r - l) * v; },
[](ll v) { return v / 2; });
auto calc_tax = [&](ll a, ll b) { return lst.get_query(a, b); };
auto merge = [&](ll a, ll b) { return a + b; };
ll Q;
cin >> Q;
ll ans = 0;
while(Q--) {
ll u, v;
cin >> u >> v;
u--; v--;
ans += hld.query<ll>(u, v, calc_tax, 0, merge);
ll uid = hld.hld_id[u];
ll vid = hld.hld_id[v];
if(vid < uid) swap(uid, vid);
lst.update_query(uid, vid + 1, 1);
}
cout << ans << endl;
return 0;
}
kcvlex