求助!#7,#9被卡,TLE
查看原帖
求助!#7,#9被卡,TLE
884563
s_computer楼主2023/10/28 03:42

求助求助,7,9被卡,但时间复杂度应该没问题。 如果有能帮忙看看的朋友,提前感谢!

#include<bits/stdc++.h>
using namespace std;
#define int long long
int k;
int h[40010],e[40010],ne[40010],w[40010],idx;
int use[20010];
int d[20010];
int f[20010],siz[20010];
int cnt,Siz,rt;
void add(const int &a,const int &b,const int &c)
{
	w[idx]=c,e[idx]=b,ne[idx]=h[a],h[a]=idx++;
	w[idx]=c,e[idx]=a,ne[idx]=h[b],h[b]=idx++;
}
//求重心
void getroot(const int &x,const int &fa)//x为当前点,fa为父亲节点
{
    f[x]=0,siz[x]=1;//f表示这个点最大子树的大小,siz是这个点子树大小的和
    for(int i=h[x];i!=-1;i=ne[i])//枚举儿子
      {
      	int y=e[i];
      	if(use[y]||y==fa) continue;//use表示之前遍历过了,这里没啥用
      	getroot(y,x);//往下遍历
      	f[x]=max(f[x],siz[y]);//更新f
      	siz[x]+=siz[y];
      }
    f[x]=max(f[x],Siz-siz[x]);//Siz表示在现在这棵子树中点的总数,开始时Siz=n,除了枚举的儿子所在的子树外,还有一棵子树是上面的那一堆,容斥原理
    if(f[x]<f[rt]) rt=x;//更新root
}

//求到重心的距离

int findunder(int l,const int &x)//找下界,r左移
{
	int ans=0,r=cnt;
	while(l<=r)
	{
		int mid(l+r>>1);
		if(d[mid]<x) l=mid+1;
		else ans=mid,r=mid-1;
	}
	return ans;
}

int findup(int l,const int &x)//找上界
{
	int ans=0,r=cnt;
	while(l<=r)
	{
		int mid(l+r>>1);
		if(d[mid]<=x) ans=mid,l=mid+1;
		else r=mid-1;
	}
	return ans;
}
void getd(const int &x,const int &fa,const int &dis)
{
	for(int i=h[x];i!=-1;i=ne[i])
	{
		int j=e[i];
		if(use[j]||j==fa) continue;
		d[++cnt]=dis+w[i];
		getd(j,x,d[cnt]);
		
	}
}
//求答案
int getans(const int &x,const int &dis,const int&k)
{
	d[cnt=1]=dis;
	getd(x,0,dis);
	
	sort(d+1,d+1+cnt);
	int l=1,ans=0;
	while(l<cnt&&d[l]+d[cnt]<k) l++;
	while(l<cnt&&d[l]<=k-d[l])//保证要找的在后面
	{
		int d1=findunder(l,k-d[l]),d2=findup(l,k-d[l]);//也可以用lower_bound()和upper_bound()实现
		if(d2>=d1)ans += d2-d1+1;//ans表示符合要求的
		l++;
	}
	return ans;
}
int ans=0;//以x点为重心的树产生的符合k的答案
//分治划分

void fz(const int &x,int k)//x就是树根
{
	//cout<<"x:"<<x<<endl;
	use[x]=1;
	ans += getans(x,0,k);//
	//printf("x=%d,ans1=%d\n",x,ans);
	for(int i=h[x];i!=-1;i=ne[i])
	{
		int j=e[i];
		if(use[j]) continue;
		int dis=w[i];
		ans -= getans(j,dis,k);
		//	printf("x=%d,ans2=%d\n",x,ans);
		Siz=siz[j],rt=0;
		getroot(j,x);//找子树中的重心
	//		printf("%d kid-ans %d",x,rt);
		//	rts[j]=rt;
		fz(rt,k);	
	}
}

signed main()
{
	f[0]=1e9+7;
	memset(h,-1,sizeof h);
	int n,m;
	scanf("%lld%lld",&n,&m);
	for(int i=0;i<n-1;i++)
	{
		int a,b,c;
		scanf("%lld%lld%lld",&a,&b,&c);
		add(a,b,c);
	}
	/*for(int i=1;i<=n;i++)
	{
		printf("%d:",i);
		for(int j=h[i];j!=-1;j=ne[j]) printf("%d ",e[j]);
		printf("\n");
	}*/
	Siz=n;
	getroot(1,1);
	//for(int i=1;i<=n;i++) cout<<i<<" f:"<<f[i]<<" siz:"<<siz[i]<<endl;
	//cout<<"rt:"<<rt<<endl;
	int root=rt;
	int q[100];
	for(int i=0;i<m;i++)
	{
		
		scanf("%lld",&q[i]);
		//memset(use,0,sizeof use);
	}
	for(int i=0;i<m;i++)
	{	
		ans=0;
		for(int i=0;i<=n;i++)use[i]=0;
		fz(root,q[i]);
		if(ans) printf("AYE\n");
		else printf("NAY\n");
	}
	
}
2023/10/28 03:42
加载中...