BZOJ 2117: [2010国家集训队]Crash的旅游计划 动态点分治+二分

感觉现在写点分治可快了~

二分答案,就可以将求第 $k$ 大转换成一个判断问题,直接拿点分树判断一下就行了. 

#include <cstdio> 
#include <vector> 
#include <algorithm>  
#define N 100004 
#define setIO(s) freopen(s".in","r",stdin) 
using namespace std;   
int n,edges,K; 
int hd[N],to[N<<1],nex[N<<1],val[N<<1];  
void add(int u,int v,int c)
{
	nex[++edges]=hd[u],hd[u]=edges,to[edges]=v,val[edges]=c; 
}   
namespace tree
{ 
	int size[N],son[N],fa[N],top[N],dep[N],dis[N]; 
	void dfs1(int u,int ff)
	{ 
		fa[u]=ff,size[u]=1; 
		for(int i=hd[u];i;i=nex[i]) 
			if(to[i]!=ff) 
			{ 
				dep[to[i]]=dep[u]+1,dis[to[i]]=dis[u]+val[i]; 
				dfs1(to[i],u); 
				size[u]+=size[to[i]]; 
				if(size[to[i]]>size[son[u]]) son[u]=to[i]; 
			}
	} 
	void dfs2(int u,int tp)
	{    
		top[u]=tp; 
		if(son[u]) dfs2(son[u],tp); 
		for(int i=hd[u];i;i=nex[i]) 
			if(to[i]!=fa[u]&&to[i]!=son[u]) 
				dfs2(to[i],to[i]);      
	}
	int LCA(int x,int y)
	{
		while(top[x]!=top[y]) 
			dep[top[x]]>dep[top[y]]?x=fa[top[x]]:y=fa[top[y]]; 
		return dep[x]<dep[y]?x:y;    
 	} 
 	int Dis(int x,int y)
 	{
 		return dis[x]+dis[y]-(dis[LCA(x,y)]<<1);    
 	} 
};  
vector<int>F[N],G[N];     
int root,sn; 
int mx[N],size[N],vis[N],Fa[N];      
void dfs(int u,int ff)
{
	size[u]=1; 
	for(int i=hd[u];i;i=nex[i]) 
		if(!vis[to[i]]&&to[i]!=ff) 
			dfs(to[i],u),size[u]+=size[to[i]]; 
} 
void getroot(int u,int ff)
{
	size[u]=1,mx[u]=0; 
	for(int i=hd[u];i;i=nex[i]) 
		if(to[i]!=ff&&!vis[to[i]])  
			getroot(to[i],u),size[u]+=size[to[i]],mx[u]=max(mx[u],size[to[i]]); 
	mx[u]=max(mx[u],sn-size[u]);  
	if(mx[u]<mx[root]) root=u; 
}  
void calc(int u,int ff,int dep,int rt) 
{  
	F[rt].push_back(dep);     
	if(Fa[rt]) G[rt].push_back(tree::Dis(Fa[rt], u));          
	for(int i=hd[u];i;i=nex[i]) 
		if(to[i]!=ff&&!vis[to[i]]) 
			calc(to[i],u,dep+val[i],rt);     
}
void prepare(int u)
{
	vis[u]=1; 
	calc(u,0,0,u);    
	F[u].push_back(1000000004);       
	sort(F[u].begin(),F[u].end()); 
	if(Fa[u]) 
	{
		G[u].push_back(1000000004); 
		sort(G[u].begin(),G[u].end());     
	}
	for(int i=hd[u];i;i=nex[i]) 
		if(!vis[to[i]]) 
			dfs(to[i],u),sn=size[to[i]],root=0,getroot(to[i],u),Fa[root]=u,prepare(root);     
} 
int query(int u,int k) 
{   
	int U=u, re=upper_bound(F[u].begin(),F[u].end(),k)-F[u].begin()-1;       
	for(;Fa[u];u=Fa[u]) 
	{
		int dis=tree::Dis(Fa[u],U); 
		if(dis<=k) 
		{
			re+=(upper_bound(F[Fa[u]].begin(),F[Fa[u]].end(),k-dis)-F[Fa[u]].begin());
			re-=(upper_bound(G[u].begin(),G[u].end(),k-dis)-G[u].begin()); 
		}
	}           
	return re;    
}
int main() 
{
	int i,j,tot=0; 
	char ss[2]; 
	// setIO("input"); 
	scanf("%s%d%d",ss,&n,&K);  
	for(i=1;i<n;++i) 
	{
		int a,b,c; 
		scanf("%d%d%d",&a,&b,&c),add(a,b,c),add(b,a,c),tot+=c; 
 	} 
 	tree::dfs1(1,0);  
 	tree::dfs2(1,1); 
 	mx[0]=sn=n,root=0,getroot(1,0),prepare(root);
  	for(i=1;i<=n;++i) 
 	{
 		int l=1,r=tot,mid,ans=0; 
 		while(l<=r) 
 		{
 			mid=(l+r)>>1; 
 			if(query(i,mid)>=K) 
 			{
 				ans=mid,r=mid-1; 
 			}
 			else l=mid+1;       
 		}
 		printf("%d\n",ans);     
 	}
	return 0; 
}

  

posted @ 2019-09-03 20:08  EM-LGH  阅读(203)  评论(0编辑  收藏  举报