結果
問題 | No.399 動的な領主 |
ユーザー | Min_25 |
提出日時 | 2017-09-17 13:31:35 |
言語 | C++14 (gcc 12.3.0 + boost 1.83.0) |
結果 |
AC
|
実行時間 | 33 ms / 2,000 ms |
コード長 | 5,124 bytes |
コンパイル時間 | 1,159 ms |
コンパイル使用メモリ | 105,196 KB |
実行使用メモリ | 12,928 KB |
最終ジャッジ日時 | 2024-11-08 01:52:56 |
合計ジャッジ時間 | 3,425 ms |
ジャッジサーバーID (参考情報) |
judge1 / judge3 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 2 ms
5,248 KB |
testcase_01 | AC | 2 ms
5,248 KB |
testcase_02 | AC | 2 ms
5,248 KB |
testcase_03 | AC | 2 ms
5,248 KB |
testcase_04 | AC | 2 ms
5,248 KB |
testcase_05 | AC | 4 ms
5,248 KB |
testcase_06 | AC | 33 ms
8,156 KB |
testcase_07 | AC | 33 ms
8,188 KB |
testcase_08 | AC | 32 ms
8,060 KB |
testcase_09 | AC | 32 ms
8,156 KB |
testcase_10 | AC | 3 ms
5,248 KB |
testcase_11 | AC | 4 ms
5,248 KB |
testcase_12 | AC | 24 ms
8,264 KB |
testcase_13 | AC | 24 ms
8,188 KB |
testcase_14 | AC | 18 ms
12,796 KB |
testcase_15 | AC | 18 ms
12,928 KB |
testcase_16 | AC | 17 ms
10,492 KB |
testcase_17 | AC | 32 ms
8,064 KB |
testcase_18 | AC | 32 ms
8,060 KB |
ソースコード
#include <cstdio> #include <cassert> #include <cmath> #include <cstring> #include <iostream> #include <algorithm> #include <vector> #include <map> #include <set> #include <functional> #include <stack> #include <queue> #include <tuple> #define getchar getchar_unlocked #define putchar putchar_unlocked #define _rep(_1, _2, _3, _4, name, ...) name #define rep2(i, n) rep3(i, 0, n) #define rep3(i, a, b) rep4(i, a, b, 1) #define rep4(i, a, b, c) for (int i = int(a); i < int(b); i += int(c)) #define rep(...) _rep(__VA_ARGS__, rep4, rep3, rep2, _)(__VA_ARGS__) using namespace std; using i64 = long long; using u8 = unsigned char; using u32 = unsigned; using u64 = unsigned long long; using f80 = long double; int get_int() { int c, n; while ((c = getchar()) < '0'); n = c - '0'; while ((c = getchar()) >= '0') n = n * 10 + (c - '0'); return n; } class RootedTree { private: struct InputEdge { int from, to; }; template <typename T> struct Range { struct Iterator { T& operator * () const { return *iter; } bool operator != (const Iterator& rhs) const { return iter != rhs.iter; } void operator ++ () { ++iter; } T* operator + (int i) const { return iter + i; } size_t operator - (const Iterator rhs) const { return iter - rhs.iter; } T* iter; }; Range(T* f, T* l) : first({f}), last({l}) {} T operator [] (int i) { return *(first + i); } size_t size() const { return last - first; } Iterator& begin() { return first; } Iterator& end() { return last; } Iterator first, last; }; public: RootedTree(int N, int M=0) : N(N), ofs(N + 1), par(N), vid(N), head(N), heavy(N), len(N) { if (M > 0) in.reserve(M); } Range<int> operator [] (int u) { return Range<int>(&edges[ofs[u]], &edges[ofs[u + 1]]); } void add_edge(int u, int v) { in.push_back({u, v}); } void build(int root) { init(), dfs(root), bfs(root); } int lca(int u, int v) const { for (; head[u] != head[v]; u = par[head[u]]) if (vid[u] < vid[v]) swap(u, v); return vid[u] > vid[v] ? v : u; } pair< vector<int>, vector< pair<int, int> > > signed_euler_tour(int root) { range.resize(N); tour.resize(2 * N); int id = 0; e_rec(root, id); return {tour, range}; } vector<int> get_path(int u, int v) const { vector<int> pu, pv; int s = 0; while (head[u] != head[v]) { if (vid[u] < vid[v]) swap(u, v), swap(pu, pv), s ^= 1; for (int w = par[head[u]]; u != w; u = par[u]) pu.push_back(u); } if (vid[u] < vid[v]) swap(u, v), swap(pu, pv), s ^= 1; for (; vid[u] != vid[v]; u = par[u]) pu.push_back(u); pu.push_back(u); if (s) swap(pu, pv); reverse(pv.begin(), pv.end()); for (auto& w : pv) pu.push_back(w); return pu; } int parent(int u) const { return par[u]; } vector<int> get_order() const { vector<int> order(N); for (int i = 0; i < N; ++i) order[vid[i]] = i; return order; } private: void e_rec(int u, int& id, int p=-1) { tour[id] = u; range[u].first = id++; for (auto& v : (*this)[u]) if (v != p) e_rec(v, id, u); tour[id] = ~u; range[u].second = id++; } void bfs(int root) { vector<int> que(N); int qh = 0, qt = 0, id = 0; que[qt++] = root; for (; qh < qt; ) { int u = que[qh++]; for (int v = u; v >= 0; v = heavy[v]) { vid[v] = id++, head[v] = u; for (auto& w : (*this)[v]) if (w != par[v] && w != heavy[v]) que[qt++] = w; } len[u] = id - vid[u]; } } int dfs(int u, int p=-1) { int s = 1, best = 0, h = -1; par[u] = p; for (auto& v : (*this)[u]) if (v != p) { int c = dfs(v, u); if (c > best) best = c, h = v; s += c; } heavy[u] = h; return s; } void init() { edges.resize(2 * in.size()); for (auto& e : in) ofs[e.from + 1]++, ofs[e.to + 1]++; for (int i = 1; i <= N; ++i) ofs[i] += ofs[i - 1]; for (auto& e : in) edges[ofs[e.from]++] = e.to, edges[ofs[e.to]++] = e.from; for (int i = N; i > 0; --i) ofs[i] = ofs[i - 1]; ofs[0] = 0; } private: int N; vector<InputEdge> in; vector<int> ofs, edges; vector<int> par, vid, head, heavy, len; vector< pair<int, int> > range; vector<int> tour; }; void solve() { int N; while (~scanf("%d", &N)) { auto g = RootedTree(N); rep(i, N - 1) { int u = get_int() - 1, v = get_int() - 1; g.add_edge(u, v); } g.build(0); vector<int> cumu(N); int M = get_int(); rep(i, M) { int u = get_int() - 1, v = get_int() - 1; int lca = g.lca(u, v), p = g.parent(lca); cumu[u] += 1; cumu[v] += 1; cumu[lca] -= 1; if (p >= 0) cumu[p] -= 1; } auto order = g.get_order(); i64 ans = 0; rep(i, N) { int u = order[N - 1 - i], p = g.parent(u); ans += i64(cumu[u]) * (cumu[u] + 1) / 2;; if (p >= 0) cumu[p] += cumu[u]; } printf("%lld\n", ans); } } int main() { clock_t beg = clock(); solve(); clock_t end = clock(); fprintf(stderr, "%.3f sec\n", double(end - beg) / CLOCKS_PER_SEC); return 0; }