zoukankan      html  css  js  c++  java
  • [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;
    	}
    } 
    
  • 相关阅读:
    形近词辨析
    anger,fury,rage,indignation,ire区别
    熟词僻义
    fate,destiny,luck,doom区别
    whk 学习笔记
    常见词根
    个人简介
    CF883D Packmen Strike Back
    CF859E Desk Disorder
    CF140E New Year Garland
  • 原文地址:https://www.cnblogs.com/dixiao/p/14823842.html
Copyright © 2011-2022 走看看