結果
問題 | No.399 動的な領主 |
ユーザー |
|
提出日時 | 2024-07-30 23:56:42 |
言語 | C++23 (gcc 13.3.0 + boost 1.87.0) |
結果 |
WA
|
実行時間 | - |
コード長 | 5,354 bytes |
コンパイル時間 | 1,420 ms |
コンパイル使用メモリ | 111,552 KB |
実行使用メモリ | 17,024 KB |
最終ジャッジ日時 | 2024-07-30 23:56:48 |
合計ジャッジ時間 | 5,429 ms |
ジャッジサーバーID (参考情報) |
judge2 / judge5 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
other | AC * 8 WA * 11 |
ソースコード
#line 1 "playground_A.cpp"#include <iostream>#line 1 "/home/samejima/CompetitiveProgramming/library/graph/tree/heavy_light_decomposition.hpp"#include <vector>#include <algorithm>#include <cassert>#include <utility>#line 1 "/home/samejima/CompetitiveProgramming/library/graph/graph_template.hpp"#line 5 "/home/samejima/CompetitiveProgramming/library/graph/graph_template.hpp"template <typename T>struct Edge {int from; int to;T cost;Edge(int _from, int _to, T _cost) : from(_from), to(_to), cost(_cost) {}// unweightedEdge(int _from, int _to) : from(_from), to(_to), cost(T(1)) {}bool operator==(const Edge& rhs) {return from == rhs.from && to == rhs.to && cost == rhs.cost;}};template <typename T>struct Graph : std::vector<std::vector<Edge<T>>> {using std::vector<std::vector<Edge<T>>>::vector; // inherit constructorsvoid add_edge(int i, Edge<T> e) {(*this)[i].push_back(e);}// weightedvoid add_edge(int _from, int _to, T _cost) {(*this)[_from].push_back(Edge(_from, _to, _cost));}// unweightedvoid add_edge(int _from, int _to) {(*this)[_from].push_back(Edge(_from, _to, T(1)));}};#line 10 "/home/samejima/CompetitiveProgramming/library/graph/tree/heavy_light_decomposition.hpp"// cf : https://ngtkana.hatenablog.com/entry/2024/06/24/200138struct Interval {// i : interval のもっとも根に近い頂点のid// j : interval のもっとも葉に近い頂点のid// last : LCAを含む interval であるかどうか// reverse : from → to と i → jが逆向きかどうかint i, j;bool last;bool reverse;Interval(int _i, int _j, bool _last, bool _reverse) : i(_i), j(_j), last(_last), reverse(_reverse) {}};using Path = std::vector<Interval>;struct HLD {//vector<vector<int>>children;std::vector<int>parent;std::vector<int> id;std::vector<int> id2;std::vector<int> head;std::vector<int>depth;Graph<int>graph;HLD (int N) : parent(std::vector<int>(N, -1)), id(std::vector<int>(N)), id2(std::vector<int>(N)), head(std::vector<int>(N)), depth(std::vector<int>(N)), graph(N) {}void build(int root=0) {dfs_sz(root);int k = 0; dfs_hld(root, k);}int dfs_sz(int v) {int ret = 1, mx_sz = 0;for (Edge<int>& nxt : graph[v]) {if (nxt.to == parent[v]) continue;parent[nxt.to] = v;depth[nxt.to] = depth[v] + 1;int sz = dfs_sz(nxt.to);ret += sz;if (mx_sz < sz) {mx_sz = sz;std::swap(graph[v][0], nxt);}}return ret;}void dfs_hld(int v, int& k) {id[v] = k; k++;for (Edge e : graph[v]) {if (e.to == parent[v]) continue;head[e.to] = (e == graph[v][0] ? head[v] : e.to);dfs_hld(e.to, k);}id2[v] = k;}int lca(int u, int v) {while (true) {if (id[u] > id[v]) std::swap(u, v);if (head[u] == head[v]) return u;v = parent[head[v]];}}Path get_path(int u, int v) {Path upath, vpath;while (head[u] != head[v]) {// ちなみにu,vのdepthの大小関係は変わり続けることもある。// 10 → 12など。// v's head is deeperif (depth[head[v]] >= depth[head[u]]) {assert(depth[head[v]] >= depth[head[u]]);/*/ : heavy edge.... : light edgehead[u]//...u .../ head[v]/ \/ \/ v*/// u→v なのでreverse=falsevpath.emplace_back(id[head[v]], id[v], false, false);v = parent[head[v]];}// u's head is deeperelse if (depth[head[v]] < depth[head[u]]) {/*/ : heavy edge.... : light edgehead[v]//...v .../ head[u]/ \/ \/ u*///upath.emplace_back(id[head[u]], id[u], false, true);u = parent[head[u]];}}// v is deeper/*u// ←↓/v*/if (depth[v] > depth[u]) {upath.emplace_back(id[u], id[v], true, false);}// u is deeper/*v// →↑/u*/else {upath.emplace_back(id[v], id[u], true, true);}Path retpath = upath;reverse(vpath.begin(), vpath.end());for (Interval path : vpath) retpath.push_back(path);return retpath;}std::pair<int,int> subtree_query(int r) {assert(r < int(id.size()));return std::make_pair(id[r], id2[r]);}};#line 3 "playground_A.cpp"using namespace std;int main() {int N; cin >> N;HLD hld(N);for (int i=0; i<N-1; i++) {int u, v; cin >> u >> v;u--;v--;hld.graph.add_edge(u,v);hld.graph.add_edge(v,u);}hld.build();vector<int> cusum(N+1);int Q; cin >> Q;for (int q=0; q<Q; q++) {int A, B; cin >> A >> B;A--;B--;for (Interval intv : hld.get_path(A,B)) {cusum[intv.i] += 1;cusum[intv.j+1] -= 1;}}long ans = 0;for (int i=0; i<N; i++) {cusum[i+1] += cusum[i];ans += cusum[i] * (cusum[i] + 1) / 2;}cout << ans << endl;}