zoukankan      html  css  js  c++  java
  • 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
    ",ans);     
     	}
    	return 0; 
    }
    

      

  • 相关阅读:
    安装pykeyboard模块
    Windows Defender Antivirus Service经常性出现占用CPU厉害
    Xpath 语法笔记
    通过docker部署rocketmq双主双从集群
    解决提取Mybatis多数据源公共组件“At least one base package must be specified”的问题
    设计模式-单例模式
    通过阳历生日计算星座,阴历生日,生辰八字,生肖五行
    设计模式-抽象工厂模式
    设计模式-工厂方法模式
    常用的MD5工具类
  • 原文地址:https://www.cnblogs.com/guangheli/p/11455289.html
Copyright © 2011-2022 走看看