点分治被卡得厉害,这是被卡死了还是我写假了
查看原帖
点分治被卡得厉害,这是被卡死了还是我写假了
6322
woshiren楼主2020/5/18 18:24

我的思路是先离线,然后点分治处理 calc使用了两种方式都没有过,第一种是双指针,第二种是开桶,看起来效率没有差别,求各位dalao帮忙看看。

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
struct data
{
	int to,val,next;
}edge[20005];
const int inf=15000005;
int root,cnt,rmb[10005],q[10005],head[10005],a[10005],tot,belong[10005],ans[10005],rec[105],u,v,w,n,m,size[10005],recsize=0x3f3f3f3f,dis[10005],vis[10005];
bool flag[inf];
void add(int u,int v,int w)
{
	edge[++cnt].to=v;
	edge[cnt].next=head[u];
	edge[cnt].val=w;
	head[u]=cnt;
}
void get_root(int u,int fa)
{
	int maxsize=0;
	size[u]=1;
	for (int i=head[u];i;i=edge[i].next)
	{
		int v=edge[i].to;
		if (v==fa||vis[v]) continue;
		get_root(v,u);
		size[u]+=size[v];
		maxsize=max(size[v],maxsize);
	}
	maxsize=max(maxsize,n-size[u]);
	if (maxsize<recsize)
	{
		root=u;
		recsize=maxsize;
	}
}
void dfs(int now,int rt,int fa)
{
	//a[++tot]=now;
	//belong[now]=cnt;
	rmb[++rmb[0]]=dis[now];
	for (int i=head[now];i;i=edge[i].next)
	{
		int v=edge[i].to;
		if (v==fa||vis[v]) continue;
		//if (now==rt) cnt++;
		dis[v]=dis[now]+edge[i].val;
		dfs(v,rt,now);
	}
}
void calc()
{
	/*for (int i=1;i<=m;i++)
	{
		int k=rec[i],l=1,r=tot;
		if (ans[i]) continue;
		while (l<r)
		{
			if (dis[a[l]]+dis[a[r]]>k) r--;
			else if (dis[a[l]]+dis[a[r]]<k) l++;
			else if (dis[a[l]]+dis[a[r]]==k&&belong[a[l]]==belong[a[r]])
				{
					if (dis[a[r]]==dis[a[r-1]]) r--;
					else l++;
				}
			else 
			{
				ans[i]=true;
				break;
			}
		}
	}*/
	int p=0;
	for (int i=head[root];i;i=edge[i].next)
	{
		int v=edge[i].to;
		if (vis[v]) continue;
		rmb[0]=0;dis[v]=edge[i].val;
		dfs(v,root,root);
		for (int j=rmb[0];j;j--)
			for (int k=1;k<=m;k++)
				if (rec[k]>=rmb[j]) ans[k]|=flag[rec[k]-rmb[j]];
		for (int j=rmb[0];j;j--)
			q[++p]=rmb[j],flag[rmb[j]]=true;
	}		
	for (int i=1;i<=p;i++)
		flag[q[i]]=false;
}
bool cmp(int x,int y)
{
	return dis[x]<dis[y];
}
void work()
{
	cnt=0;dis[root]=0;tot=0;vis[root]=true;
	flag[0]=1;
	//dfs(root,root,0);
	//sort(a+1,a+1+tot,cmp);
	calc();
	int t=root;
	for (int i=head[t];i;i=edge[i].next)
	{
		if (vis[edge[i].to]) continue;
		recsize=0x3f3f3f3f;
		get_root(edge[i].to,t);
		work();
	}
}
int read()
{
	char c=getchar();int num=0;
	while (c<'0'||c>'9') c=getchar();
	while (c>='0'&&c<='9') {num*=10;num+=c-48;c=getchar();}
	return num;
}
int main()
{
	n=read();m=read();
	for (int i=1;i<n;i++)
	{
		u=read(),v=read(),w=read();
		add(u,v,w);add(v,u,w);
	}
	for (int i=1;i<=m;i++)
	{
		int k;
		k=read();
		rec[i]=k;
	}
	get_root(1,0);
	work();
	for (int i=1;i<=m;i++)
		printf(ans[i]?"AYE\n":"NAY\n");
	return 0;
}
2020/5/18 18:24
加载中...