sub3 T了两个点#1#4
查看原帖
sub3 T了两个点#1#4
315205
Kniqht楼主2023/9/29 18:31

rt,点分治求找出t的原因

400ms,但是题目要求200ms

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=1e5+10,M=N*2,K=1e7+10;
int n,Q,m,qt,f[K]; 
int h[N],e[M],ne[M],idx;
ll w[M],q[N];
bool st[N];
void add(int a,int b,int c){
	e[idx]=b,ne[idx]=h[a],w[idx]=c,h[a]=idx++;
}
ll get_sz(int u,int fa){
	if(st[u]) return 0;
	int res=1;//子树大小初始为1别赋值成0了 
	for(int i=h[u];~i;i=ne[i]){
		int j=e[i];
		if(j==fa) continue;
		res+=get_sz(j,u);
	}
	return res;
}
void get_dist(int u,int fa,ll dis){
	if(st[u]) return;
	q[++qt]=dis;
	for(int i=h[u];~i;i=ne[i]){
		int j=e[i];
		if(j==fa)continue;
		get_dist(j,u,dis+w[i]);
	}
}
ll get_wc(int u,int fa,int tot,int &rt){
	if(st[u]) return 0;
	ll res=1,ans=0;
 	for(int i=h[u];~i;i=ne[i]){
		int j=e[i];
		if(j==fa)continue;
		ll t=get_wc(j,u,tot,rt);
		ans=max(ans,t);res+=t; 
	}
	ans=max(ans,tot-res);
	if(ans<=tot/2) rt=u;
	return res;
}

ll check(ll a[],int X){
	ll res=0;
	for(int i=1;i<=X;i++)
		if(a[i]<=m) f[a[i]]++;
	for(int i=1;i<=X;i++)
		if(a[i]<=m&&f[m-a[i]]){
			if(m-a[i]==a[i]) res+=f[a[i]]-1;
			else res+=f[m-a[i]];
		}
	for(int i=1;i<=X;i++) 
		if(a[i]<=m)f[a[i]]=0;
	return res;
}
ll p[N];
ll calc(int u){
	if(st[u]) return 0;
	int sz=get_wc(u,-1,get_sz(u,-1),u),pt=0;ll res=0;
	st[u]=1;
	for(int i=h[u];~i;i=ne[i]){
		int j=e[i];
		qt=0;
		get_dist(j,u,w[i]);
		res-=check(q,qt);
		for(int k=1;k<=qt;k++){
			p[++pt]=q[k];
			if(q[k]==m) res++;
		}
	}
	res+=check(p,pt);
	for(int i=h[u];~i;i=ne[i]) res+=calc(e[i]);
	return res; 
}
int main(){
	memset(h,-1,sizeof(h));
    scanf("%d%d",&n,&Q);
    for(int i=1;i<n;i++){
    	int a,b,c;scanf("%d%d%d",&a,&b,&c);
    	add(a,b,c);add(b,a,c);
	}
	while(Q--){
		memset(st,0,sizeof(st));
		scanf("%d",&m);
		int t=calc(1);
		printf(t?"AYE":"NAY");
		putchar('\n');
	}
    return 0;
}

2023/9/29 18:31
加载中...