[AGC002D] Stamp Rally

确实有想到重构树,不过没有继续下去的思路。
可能是对重构树的性质不太懂。

这种题目我们可以二分答案,考虑怎么(check)呢,整体二分+并查集,建出重构树,找去第一个小于这个数的方点,查询他的子树大小。
不过因为是两个点,要注意两点的满足性质的方点是同一个点的情况。

[AGC002D] Stamp Rally
#include<iostream>
#include<cstdio>
#include<algorithm>
#define ll long long 
#define N 200005

struct P{int to,s;ll v;}e[N];

inline bool operator < (P a,P b){return a.v < b.v;} 

ll n,m;

ll tot;

ll fa[N];

inline ll find(int x){return (fa[x] == x) ? x : fa[x] = find(fa[x]);} 

ll v[N << 1],head[N << 1],cnt;

struct E{int to,next;}p[N << 2];

inline void add(int x,int y){
	p[++cnt].to = y;
	p[cnt].next = head[x];
	head[x] = cnt;
} 

inline void build(){
	ll cnt = 0;
	tot = n;
	for(int i = 1;i <= m,cnt < n - 1;++i){
		int x = e[i].s,y = e[i].to;
		int fx = find(x),fy = find(y);
		if(fx == fy)
		continue;
		++tot;
		add(tot,fx);
		add(tot,fy);
		v[tot] = e[i].v;
		fa[tot] = fa[fx] = fa[fy] = tot;
		++cnt;
	}
}

ll f[N << 1][30],siz[N << 1],dep[N << 1];

inline void dfs(int x,int fi){
	f[x][0] = fi;
	dep[x] = dep[fi] + 1;
	if(x <= n)
	siz[x] = 1;
	for(int i = 1;i <= 24;++i)
	f[x][i] = f[f[x][i - 1]][i - 1];
	for(int i = head[x];i;i = p[i].next){
		int v = p[i].to;
		dfs(v,x);
		siz[x] += siz[v];
	}
}

inline ll find_rt(int u,int x){
	for(int i = 24;i >= 0;--i){
		if(v[f[u][i]] <= x)
		u = f[u][i];
	}
	return u;
}

ll q;

int main(){
	scanf("%lld%lld",&n,&m);
	for(int i = 1;i <= m;++i){
		scanf("%d%d",&e[i].s,&e[i].to);
		e[i].v = i;
	}
	for(int i = 1;i <= n;++i)
	fa[i] = i;
	std::sort(e + 1,e + m + 1);
	build();
//	puts("");
	dfs(find(1),0); 
	v[0] = 0x3f3f3f3f;
	scanf("%lld",&q);
	for(int i = 1;i <= q;++i){
		ll x,y,z;
		scanf("%lld%lld%lld",&x,&y,&z);
		ll l = 1,r = m,ans = 0;
		bool flag = 0;
		while(l <= r){
			ll mid = (l + r) >> 1;
			ll fx = find_rt(x,mid),fy = find_rt(y,mid);
//			std::cout<<mid<<" "<<fx<<" "<<fy<<std::endl;
			if(fx == fy)
			flag = (siz[fx] >= z);
			else
			flag = (siz[fx] + siz[fy] >= z);
			if(flag)
			ans = mid,r = mid - 1;
			else
			l = mid + 1;
		}
		std::cout<<ans<<std::endl;
	}
} 
原文地址:https://www.cnblogs.com/dixiao/p/14823842.html