結果

問題 No.399 動的な領主
ユーザー manjuuu_onsenmanjuuu_onsen
提出日時 2024-02-26 01:32:07
言語 C++14
(gcc 12.3.0 + boost 1.83.0)
結果
AC  
実行時間 520 ms / 2,000 ms
コード長 3,691 bytes
コンパイル時間 2,192 ms
コンパイル使用メモリ 186,592 KB
実行使用メモリ 23,940 KB
最終ジャッジ日時 2024-09-29 11:31:49
合計ジャッジ時間 8,418 ms
ジャッジサーバーID
(参考情報)
judge3 / judge4
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
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 3 ms
5,248 KB
testcase_05 AC 35 ms
5,248 KB
testcase_06 AC 506 ms
17,752 KB
testcase_07 AC 492 ms
17,784 KB
testcase_08 AC 488 ms
17,864 KB
testcase_09 AC 497 ms
17,828 KB
testcase_10 AC 5 ms
6,816 KB
testcase_11 AC 29 ms
6,816 KB
testcase_12 AC 383 ms
18,224 KB
testcase_13 AC 376 ms
18,292 KB
testcase_14 AC 149 ms
23,928 KB
testcase_15 AC 188 ms
23,940 KB
testcase_16 AC 271 ms
20,892 KB
testcase_17 AC 520 ms
17,800 KB
testcase_18 AC 500 ms
18,000 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