結果

問題 No.399 動的な領主
ユーザー ku_senjanku_senjan
提出日時 2023-12-28 23:22:23
言語 C++17
(gcc 12.3.0 + boost 1.83.0)
結果
AC  
実行時間 645 ms / 2,000 ms
コード長 2,637 bytes
コンパイル時間 5,110 ms
コンパイル使用メモリ 273,736 KB
実行使用メモリ 22,812 KB
最終ジャッジ日時 2024-09-27 15:55:03
合計ジャッジ時間 11,116 ms
ジャッジサーバーID
(参考情報)
judge1 / judge4
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 2 ms
6,812 KB
testcase_01 AC 2 ms
6,812 KB
testcase_02 AC 2 ms
6,944 KB
testcase_03 AC 2 ms
6,944 KB
testcase_04 AC 4 ms
6,940 KB
testcase_05 AC 42 ms
6,944 KB
testcase_06 AC 607 ms
17,848 KB
testcase_07 AC 604 ms
17,880 KB
testcase_08 AC 645 ms
17,912 KB
testcase_09 AC 608 ms
17,920 KB
testcase_10 AC 6 ms
6,940 KB
testcase_11 AC 35 ms
6,940 KB
testcase_12 AC 465 ms
18,380 KB
testcase_13 AC 446 ms
18,224 KB
testcase_14 AC 160 ms
22,804 KB
testcase_15 AC 206 ms
22,812 KB
testcase_16 AC 305 ms
20,348 KB
testcase_17 AC 631 ms
17,876 KB
testcase_18 AC 617 ms
18,004 KB
権限があれば一括ダウンロードができます

ソースコード

diff #

#include <bits/stdc++.h>
#include <atcoder/all>
using namespace std;
using namespace atcoder;

class HeavyLightDecomposition{
	private:
		int n;
		vector<vector<int>> g;
		vector<int> siz, par, dep, top, in, out;

		void dfs_siz(int v, int p){
			par[v] = p;
			for(int &nv:g[v]){
				if(nv==p){
					if(nv==g[v].back()) break;
					swap(nv, g[v].back());
				}
				dfs_siz(nv, v);
				siz[v] += siz[nv];
				if(siz[nv]>siz[g[v][0]]){
					swap(nv, g[v][0]);
				}
			}
		}

		void dfs_hld(int v, int p, int &i){
			in[v] = i++;
			for(int &nv:g[v]){
				if(nv==p) continue;
				dep[nv] = dep[v]+1;
				if(nv==g[v][0]) top[nv] = top[v];
				else top[nv] = nv;
				dfs_hld(nv, v, i);
			}
			out[v] = i;
		}

	public:
		HeavyLightDecomposition(const int _n=0):
			n(_n), g(_n), siz(_n, 1), par(_n, -1),
			dep(_n), top(_n), in(_n), out(_n){}

		void add_edge(int u, int v){
			g[u].push_back(v);
			g[v].push_back(u);
		}

		void build(){
			dfs_siz(0, -1);
			int i{};
			dfs_hld(0, -1, i);
		}

		int depth(int v) const {
			return dep[v];
		}

		int lca(int u, int v) const {
			while(true){
				if(in[u]>in[v]) swap(u, v);
				if(top[u]==top[v]) return u;
				v = par[top[v]];
			}
		}

		void subtree_query(int u, const function<void(int,int)> &func) const{
			func(in[u], out[u]);
		}

		void path_node_query(int u, int v, const function<void(int,int)> &func) const {
			while(true){
				if(in[u]>in[v]) swap(u, v);
				func(max(in[u], in[top[v]]), in[v]+1);
				if(top[u]==top[v]) break;
				v = par[top[v]];
			}
		}

		void path_edge_query(int u, int v, const function<void(int,int)> &func) const {
			while(true){
				if(in[u]>in[v]) swap(u, v);
				if(top[u]==top[v]){
					if(u==v) break;
					func(in[u]+1, in[v]+1);
				}else{
					func(in[top[v]], in[v]+1);
					v = par[top[v]];
				}
			}
		}
};

struct S{
	long long value;
	int size;
};
using F = long long;

S op(S a, S b){ return {a.value+b.value, a.size+b.size}; }
S e(){ return {0, 0}; }
S mapping(F f, S x){ return {x.value + f*x.size, x.size}; }
F composition(F f, F g){ return f+g; }
F id(){ return 0; }

int main(){
	int N; cin >> N;
	HeavyLightDecomposition hld(N);
	for(int i=0; i<N-1; i++){
		int u, v; cin >> u >> v;
		u--, v--;
		hld.add_edge(u, v);
	}

	hld.build();
	vector<S> v(N, {0, 1});
	lazy_segtree<S, op, e, F, mapping, composition, id> seg(v);
	long long ans = 0;

	int Q; cin >> Q;
	for(;Q--;){
		int u, v; cin >> u >> v;
		u--, v--;
		hld.path_node_query(u, v, [&](int a, int b) -> void{
				seg.apply(a, b, 1);
				});
		hld.path_node_query(u, v, [&](int a, int b) -> void{
				ans += seg.prod(a, b).value;
				});
	}

	cout << ans << endl;
}
0