結果
問題 | No.399 動的な領主 |
ユーザー | 竹内俊暁 |
提出日時 | 2022-11-16 23:09:16 |
言語 | C++14 (gcc 12.3.0 + boost 1.83.0) |
結果 |
WA
|
実行時間 | - |
コード長 | 3,791 bytes |
コンパイル時間 | 1,862 ms |
コンパイル使用メモリ | 125,156 KB |
実行使用メモリ | 64,640 KB |
最終ジャッジ日時 | 2024-09-17 17:35:58 |
合計ジャッジ時間 | 7,384 ms |
ジャッジサーバーID (参考情報) |
judge3 / judge2 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 1 ms
5,248 KB |
testcase_01 | AC | 1 ms
5,376 KB |
testcase_02 | WA | - |
testcase_03 | WA | - |
testcase_04 | WA | - |
testcase_05 | WA | - |
testcase_06 | WA | - |
testcase_07 | WA | - |
testcase_08 | WA | - |
testcase_09 | WA | - |
testcase_10 | WA | - |
testcase_11 | WA | - |
testcase_12 | WA | - |
testcase_13 | WA | - |
testcase_14 | AC | 158 ms
64,640 KB |
testcase_15 | WA | - |
testcase_16 | AC | 294 ms
59,136 KB |
testcase_17 | WA | - |
testcase_18 | WA | - |
ソースコード
#include <algorithm> #include <bit> #include <bitset> #include <cmath> #include <cstdint> #include <iomanip> #include <iostream> #include <map> #include <queue> #include <set> #include <stack> #include <vector> #define rep(i, l, r) for(ll i = l; i <= r; i++) static const int WH = 0; static const int GR = 1; static const int BL = 2; using namespace std; using ll = long long; using ull = unsigned long long; static const ll ll_INF = 1e18; static const ll MOD = 998244353; void chmin(ll &a, ll b) { a = min(a, b); } struct LCA { vector<int> height; vector<vector<int>> anc; vector<vector<int>> linked; vector<ll> cnt; vector<ll> incr; int root; int vertex_num; LCA(int N, int root_vertex) { vertex_num = N; height = vector<int>(N + 5, -1); anc = vector<vector<int>>(N + 5, vector<int>(100, -1)); linked = vector<vector<int>>(N + 5); cnt = vector<ll>(N + 5, -1); incr = vector<ll>(N + 5, 0); root = root_vertex; } void add_edge(int u, int v) { linked[u].push_back(v); linked[v].push_back(u); } ll find_cnt(int u) { if(cnt[u] != -1) return cnt[u]; cnt[u] = 0; cnt[u] += incr[u]; for(int x:linked[u]){ if(x == find_anc(u,1)) continue; cnt[u] += find_cnt(x); } return cnt[u]; } void pass(int u, int v) { int ca = find_common_anc(u, v); incr[u]++; incr[v]++; incr[ca]--; if(ca != root) { incr[find_anc(ca, 1)]--; } } ll solve() { ll ans = 0; for(int i = 1; i <= vertex_num; i++) { ans += find_cnt(i) * (find_cnt(i) + 1) / 2; } return ans; } void find_height() { queue<int> q; q.push(root); height[root] = 0; while(q.size()) { int nv = q.front(); q.pop(); for(int x : linked[nv]) { if(height[x] == -1) { height[x] = height[nv] + 1; q.push(x); anc[x][0] = nv; } } } } int find_anc_sub(int u, int p) { // 頂点uの2^p前の頂点を求める. // cout << "sub " << u << " " << p << " " << anc[u][p] << endl; if(anc[u][p] != -1) return anc[u][p]; if(height[u] < pow_ll(2, p)) return -1; anc[u][p] = find_anc_sub(find_anc_sub(u, p - 1), p - 1); return anc[u][p]; } int find_anc(int u, int dis) { int var = 1; int p = 0; while(dis) { if(dis & 1) u = find_anc_sub(u, p); p += 1; dis >>= 1; } return u; } int find_common_anc(int u, int v) { if(u == v) return u; int left = 0; int right = min(height[u], height[v]); while(right - left > 1) { int mid = (left + right) / 2; if(find_anc(u, height[u] - mid) == find_anc(v, height[v] - mid)) left = mid; else right = mid; } return find_anc(u, height[u] - left); } ll pow_ll(ll u, ll v) { // u^v ll ans = 1; while(v > 0) { if(v & 1) ans *= u; v >>= 1; u *= u; } return ans; } }; int main() { int N; cin >> N; LCA lca(N, 1); rep(i, 1, N - 1) { int u, v; cin >> u >> v; lca.add_edge(u, v); } lca.find_height(); int Q; cin >> Q; rep(i, 1, Q) { int a, b; cin >> a >> b; lca.pass(a, b); } //lca.find_cnt(); cout << lca.solve() << endl; return 0; }