結果

問題 No.399 動的な領主
ユーザー manjuuu_onsenmanjuuu_onsen
提出日時 2024-02-26 01:32:07
言語 C++14
(gcc 12.3.0 + boost 1.83.0)
結果
AC  
実行時間 654 ms / 2,000 ms
コード長 3,691 bytes
コンパイル時間 2,881 ms
コンパイル使用メモリ 187,632 KB
実行使用メモリ 24,036 KB
最終ジャッジ日時 2024-02-26 01:32:18
合計ジャッジ時間 9,126 ms
ジャッジサーバーID
(参考情報)
judge11 / judge15
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 2 ms
6,676 KB
testcase_01 AC 2 ms
6,676 KB
testcase_02 AC 2 ms
6,676 KB
testcase_03 AC 2 ms
6,676 KB
testcase_04 AC 5 ms
6,676 KB
testcase_05 AC 41 ms
6,676 KB
testcase_06 AC 654 ms
17,868 KB
testcase_07 AC 586 ms
17,868 KB
testcase_08 AC 584 ms
17,916 KB
testcase_09 AC 588 ms
17,904 KB
testcase_10 AC 6 ms
6,676 KB
testcase_11 AC 33 ms
6,676 KB
testcase_12 AC 502 ms
18,344 KB
testcase_13 AC 449 ms
18,324 KB
testcase_14 AC 173 ms
24,036 KB
testcase_15 AC 214 ms
24,036 KB
testcase_16 AC 335 ms
20,912 KB
testcase_17 AC 629 ms
17,896 KB
testcase_18 AC 632 ms
17,908 KB
権限があれば一括ダウンロードができます
コンパイルメッセージ
main.cpp: In function 'int main()':
main.cpp:162:26: warning: structured bindings only available with '-std=c++17' or '-std=gnu++17' [-Wc++17-extensions]
  162 |                 for(auto [l,r]:s) {
      |                          ^

ソースコード

diff #

#include<bits/stdc++.h>

using namespace std;
using ll = long long;
using P = pair<int,int>;

/*
☆HLDの使い方☆
まずbuildする
①頂点に値がある場合: 
	- 代入はseg[hld.in[v]] = a[v]
	- パスクエリはfor_each_vertex(u,v)
	- 部分木クエリは hld.in[v] ~ hld.out[v]で
②辺に値がある場合:
	- 代入(aとbの間の辺に重みw)は (par[a] == b ? seg[hld.in[a]] = w : seg[hld.in[b]] = w)
	- パスクエリはfor_each_edge(u, v)
非可換だと壊れると思う
*/

struct HLD {
	int n;
	vector<int> par,in,out,head,inv,sub;
	vector<vector<int>> g;
	HLD(){};
	HLD(int n) {
		g = vector<vector<int>>(n);
		sub = par = in = out = head = inv = vector<int>(n);
	}
	void add_edge(int u, int v) {
		g[u].push_back(v);
		g[v].push_back(u);
	}
	int dfs_hld(int c, int p) {
		sub[c] = 1;
		if(p != -1) g[c].erase(find(g[c].begin(), g[c].end(), p));
		for(auto &d :g[c]) {
			par[d] = c;
			sub[c] += dfs_hld(d, c);
			if(sub[d] > sub[g[c][0]]) swap(d, g[c][0]);
		}
		return sub[c];
	}
	void dfs2(int c, int &i) {
		in[c] = i++;
		inv[in[c]] = c;
		for(auto &d : g[c]) {
			head[d] = (g[c][0] == d ? head[c] : d);
			dfs2(d,i);
		}
		out[c] = i;
	}
	void build(int r=0) {
		dfs_hld(0,-1);
		int cnt = 0;
		dfs2(0,cnt);
	}
	int lca(int u, int v) {
		while(1) {
			if(in[u] > in[v]) swap(u,v);
			if(head[u] == head[v]) return u;
			v = par[head[v]];
		}
	}
	vector<pair<int,int>> for_each_vertex(int u, int v) { //seg[in[u]] に代入
		vector<pair<int,int>> path;
		while(1) {
			if(in[u] > in[v]) swap(u,v);
			if(head[u] != head[v]) {
				path.push_back({in[head[v]], in[v] + 1});
				v = par[head[v]];
			}else {
				path.push_back({in[u],in[v]+1});
				return path;
			}
		}	
	}

	vector<pair<int,int>> for_each_edge(int u, int v) { //子に辺の情報を代入
		vector<P> path;
		while(1) {
			if(in[u] > in[v]) swap(u,v);
			if(head[u] != head[v]) {
				path.push_back({in[head[v]], in[v] + 1});
				v = par[head[v]];
			} else {
				path.push_back({in[u] + 1, in[v] + 1});
				return path;
			}
		}
	}
};

template<typename T>
struct fenwick_tree {
	int n;
	vector<T> bit;
	fenwick_tree(){};
	fenwick_tree(int n):n(n), bit(n+1,0){}
	void add(int i, T x) {
		i++;
		for(int idx=i; idx<=n; idx += (idx & (-idx))) bit[idx] += x;
	}
	T sum(int i) { 
		T s(0);
		for(int idx=i; idx>0; idx-= (idx & (-idx)) ) s += bit[idx];
		return s;
	}
	T sum(int l, int r) {return sum(r) - sum(l);}
	int lower_bound(T w) {
		if(w <= 0) return 0; 
		int x=0, r=1;
		while(r < n) r = r<<1;
		for(int len = r; len > 0; len = len>>1) {
			if(x + len < n && bit[x+len] < w) {
				w -= bit[x + len];
				x += len;
			}
		}
		return x+1;
	}
};

#include<atcoder/lazysegtree>
using namespace atcoder;
/*
☆atcoder::lazy_segtreeの使い方☆
<typename S, S (*op)(S, S), S (*e)(), typename F, S (*mapping)(F, S), F (*composition)(F, F), F (*id)()> lazy_segtree
作用素の合成composition(F f, F g) は f∘gとなる(つまりfが後から来たもの)
↓↓↓↓↓↓区間和・区間加算
*/
struct S {
	ll x;
	int l;
};
S op(S a, S b){return {a.x + b.x, a.l + b.l};}
S e(){return {0,0};}
using F = ll;
S mapping(F f, S x) {return {x.x + x.l*f,x.l};}
F composition(F f, F g){return f + g;}
F id(){return 0;}

int main()
{
	int N;
	cin>>N;
	HLD hl(N);
	for(int i=0; i<N-1; i++) {
		int u,v;cin>>u>>v;
		u--,v--;
		hl.add_edge(u,v);	
	}
	hl.build();
	lazy_segtree<S,op,e,F,mapping,composition,id> seg(N);
	for(int i=0; i<N; i++) seg.set(i, {0,1});
	int Q;
	cin>>Q;
	ll ans = 0;
	while(Q--) {
		int u,v;cin>>u>>v;
		u--,v--;
		auto s = hl.for_each_vertex(u,v);
		for(auto [l,r]:s) {
			ans += seg.prod(l,r).x + (r - l);
			seg.apply(l,r,1);
		}
	}
	cout << ans << endl;
	
}
0