ybt躲避拥挤

把查询离线会让复杂度变得非常优秀,因为每一条边只被查询一次。

#include<bits/stdc++.h>
using namespace std;
const int maxn=2e4+50,maxm=1e5+40;
int fa[maxn];
long long cnt[maxn];
int n,m,test,q,x;
long long tot;
struct mint
{
	int u,v,w;
}e[maxm];
bool cmp(mint a,mint b)
{
	return a.w < b.w;
}
struct anss
{
	int id,size;
	long long sum;
}ans[maxn];
bool cmpanssize(anss a,anss b)
{
	return a.size < b.size;	
}
bool cmpansid(anss a,anss b)
{
	return a.id < b.id;	
}
int Find(int x)
{
	if(fa[x]==x) return x;
	cnt[fa[x]]+=cnt[x];
	cnt[x]=0;
	return fa[x]=Find(fa[x]);
}
void Merge(int x,int y)
{
	int xx=Find(x),yy=Find(y);
	tot+=cnt[xx]*cnt[yy]*2;
	fa[xx]=yy;
	cnt[yy]+=cnt[xx]; 
	cnt[xx]=0;
}
int main()
{
	scanf("%d",&test);
	for(int h=1;h<=test;++h)
	{
		tot=0;
		scanf("%d%d%d",&n,&m,&q);
		for(int i=1;i<=n;++i) cnt[i]=1;
		for(int i=1;i<=m;++i) scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w);
		sort(e+1,e+m+1,cmp);
		for(int g=1;g<=q;++g)
		{
			scanf("%d",&ans[g].size);
			ans[g].id=g;
			ans[g].sum=0;
		}
		sort(ans+1,ans+q+1,cmpanssize);
	//	for(int i=1;i<=q;++q) printf("size=%d sum=%lld id=%d\n",ans[i].size,ans[i].sum,ans[i].id); 
		int place=1; 
		for(int i=1;i<=n;++i) fa[i]=i;
		for(int i=1;i<=q;++i)
		{
			for(int j=place;j<=m;++j)
			{
				if(ans[i].size < e[j].w)
				{
					place=j;
					break;	
				}
				else if(Find(e[j].u) != Find(e[j].v)) Merge(Find(e[j].u),Find(e[j].v));
			}
			ans[i].sum=tot;
		}
		sort(ans+1,ans+q+1,cmpansid);
		for(int i=1;i<=q;++i) printf("%lld\n",ans[i].sum); 
	}	
	return 0;	
}
上一篇:倍增LCA模板&ybt树上距离


下一篇:【ybt高效进阶5-3-1】B数计数(数位DP)