結果
問題 | No.399 動的な領主 |
ユーザー |
|
提出日時 | 2022-11-08 12:47:40 |
言語 | C++17 (gcc 13.3.0 + boost 1.87.0) |
結果 |
AC
|
実行時間 | 960 ms / 2,000 ms |
コード長 | 7,116 bytes |
コンパイル時間 | 2,132 ms |
コンパイル使用メモリ | 158,828 KB |
最終ジャッジ日時 | 2025-02-08 19:11:54 |
ジャッジサーバーID (参考情報) |
judge1 / judge2 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
other | AC * 19 |
ソースコード
#include <iostream>#include <vector>#include <algorithm>#include <cmath>#include <queue>#include <string>#include <map>#include <set>#include <stack>#include <tuple>#include <deque>#include <array>#include <numeric>#include <bitset>#include <iomanip>#include <cassert>#include <chrono>#include <random>#include <limits>#include <iterator>#include <functional>#include <sstream>#include <fstream>#include <complex>#include <cstring>#include <unordered_map>#include <unordered_set>#include <memory>using namespace std;// #pragma GCC optimize("O3")// #pragma GCC optimize("unroll-loops")// #pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,avx2,tune=native")// #pragma GCC target("avx512f,avx512dq,avx512cd,avx512bw,avx512vl")using ll = long long;constexpr int INF = 1001001001;// constexpr int mod = 1000000007;constexpr int mod = 998244353;template<class T>inline bool chmax(T& x, T y){if(x < y){x = y;return true;}return false;}template<class T>inline bool chmin(T& x, T y){if(x > y){x = y;return true;}return false;}constexpr int dx[] = {1, 0, -1, 0, 1, 1, -1, -1};constexpr int dy[] = {0, 1, 0, -1, 1, -1, 1, -1};struct HeavyLightDecomposition {using Graph = vector<vector<int>>;int V;Graph& g;vector<int> subtree_size, head, in, out, par, inverse;HeavyLightDecomposition(Graph& g_) :V(g_.size()), g(g_), subtree_size(V), head(V), in(V), out(V), par(V), inverse(V) {}void calc_subtree_size(int cur, int p){if(g[cur].size() && g[cur][0] == p){swap(g[cur][0], g[cur].back());}subtree_size[cur] = 1;par[cur] = p;for(auto& child : g[cur]){if(child == p) continue;calc_subtree_size(child, cur);subtree_size[cur] += subtree_size[child];if(subtree_size[g[cur][0]] < subtree_size[child]){swap(g[cur][0], child);}}}void dfs(int cur, int p, int& times){in[cur] = times++;inverse[in[cur]] = cur;for(auto& child : g[cur]){if(child == p) continue;head[child] = (g[cur][0] == child ? head[cur] : child);dfs(child, cur, times);}out[cur] = times;}void build(int root = 0){calc_subtree_size(root, -1);int t = 0;dfs(root, -1, t);}int get(int v, int k){for(;;){int u = head[v];if(in[v] - k >= in[u]){ // u, v in same groupreturn inverse[in[v] - k];}k -= in[v] - in[u] + 1;v = par[u];}}int lca(int u, int v){for(;; v = par[head[v]]){if(in[u] > in[v]) swap(u, v);if(head[u] == head[v]) return u;}}vector<pair<int, int>> get_sections(int u, int v, bool is_edge = false){vector<pair<int, int>> res;for(;; v = par[head[v]]){if(in[u] > in[v]) swap(u, v);if(head[u] == head[v]) break;res.emplace_back(in[head[v]], in[v] + 1);}res.emplace_back(in[u] + is_edge, in[v] + 1);return res;}int operator[](const int& v) const {return in[v];}int edge(int u, int v){return in[in[u] > in[v] ? u : v];}};template<typename Monoid, typename OperatorMonoid = Monoid>struct LazySegmentTree{using F = function<Monoid(Monoid, Monoid)>;using G = function<Monoid(Monoid, OperatorMonoid)>;using H = function<OperatorMonoid(OperatorMonoid, OperatorMonoid)>;int sz;vector<Monoid> data;vector<OperatorMonoid> lazy;const F f;const G g;const H h;const Monoid M1; // モノイドの単位元const OperatorMonoid OM0; // 作用素モノイドの単位元LazySegmentTree(int n, const F f, const G g, const H h, const Monoid &M1, const OperatorMonoid OM0): f(f), g(g), h(h), M1(M1), OM0(OM0){sz = 1;while(sz < n) sz <<= 1;data.assign(sz << 1, M1);lazy.assign(sz << 1, OM0);}void set(int k, const Monoid &x){data[k + sz] = x;}void build(){for(int k = sz - 1; k > 0; --k){data[k] = f(data[k << 1], data[k << 1 | 1]);}}void propagate(int k){if(lazy[k] != OM0){if(k < sz){lazy[k << 1] = h(lazy[k << 1], lazy[k]);lazy[k << 1 | 1] = h(lazy[k << 1 | 1], lazy[k]);}data[k] = g(data[k], lazy[k]);lazy[k] = OM0;}}Monoid update(int a, int b, const OperatorMonoid &x, int k = 1, int l = 0, int r = -1){if(r == -1) r = sz;propagate(k);if(r <= a || b <= l) return data[k];else if(a <= l && r <= b){lazy[k] = h(lazy[k], x);propagate(k);return data[k];}else{return data[k] = f(update(a, b, x, k << 1, l, (l + r) >> 1),update(a, b, x, k << 1 | 1, (l + r) >> 1, r));}}Monoid query(int a, int b, int k = 1, int l = 0, int r = -1){if(r == -1) r = sz;propagate(k);if(r <= a || b <= l) return M1;else if(a <= l && r <= b) return data[k];else{return f(query(a, b, k << 1, l, (l + r) >> 1),query(a, b, k << 1 | 1, (l + r) >> 1, r));}}Monoid operator[](const int &i){int k = 1, l = 0, r = sz, m;while(k < sz){propagate(k);k <<= 1;m = (l + r) >> 1;if(i + 1 <= m) r = m;else { l = m; ++k; }}propagate(k);return data[k];}};int main(){ios::sync_with_stdio(false);cin.tie(nullptr);int N, Q;cin >> N;vector<vector<int>> g(N);for(int i = 1; i < N; ++i){int u, v;cin >> u >> v;--u, --v;g[u].emplace_back(v);g[v].emplace_back(u);}HeavyLightDecomposition hld(g);hld.build();using S = pair<ll, int>;using F = int;auto op = [](S l, S r) -> S {return {l.first + r.first, l.second + r.second};};auto mapping = [](S x, F f) -> S {return {x.first + x.second * f, x.second};};auto composition = [](F f, F g) -> F {return f + g;};S e = {0, 0};F id = 0;LazySegmentTree<S, F> seg(N, op, mapping, composition, e, id);for(int i = 0; i < N; ++i){seg.set(i, {0, 1});}seg.build();cin >> Q;ll ans = 0;for(int q = 0; q < Q; ++q){int u, v;cin >> u >> v;--u, --v;auto sections = hld.get_sections(u, v);for(auto& [l, r] : sections){ans += seg.query(l, r).first + (r - l);seg.update(l, r, 1);}}cout << ans << endl;return 0;}