zoukankan      html  css  js  c++  java
  • CF516D Drazil and Morning Exercise

    cf

    luogu

    首先每个点到最远点的距离可以预处理出来,这个距离显然是这个点到树直径两端点的最大值.把那个距离记为(d_i),然后从小到大枚举(d_i),并强制它为最大的(d_i),那么前面(d_j)更小的,满足(d_i-d_jle L)的点都可以被计入答案,那么就可以维护一些点的连通情况,支持加点删点,以及维护每个连通块大小,lct即可

    考虑发掘其他性质,因为一个点的最远点一定是直径两端点之一,那么把直径上中点作为根,在直径一半边的所有点的最远点都是另一侧的直径端点,并且越往子树走,这个距离会越大.所以如果从大到小枚举最小的(d_i),那么当一个满足(d_j-d_i>L)的点(j)被删掉时,在它子树内的点会被先删掉,所以删它的时候他就是个叶子.那么考虑直接并查集维护,删点是直接给对应并查集大小(-1)即可

    #include<bits/stdc++.h>
    #define LL long long
    #define uLL unsigned long long
    #define db double
    
    using namespace std;
    const int N=1e5+10;
    LL rd()
    {
    	LL x=0,w=1;char ch=0;
    	while(ch<'0'||ch>'9'){if(ch=='-') w=-1;ch=getchar();}
    	while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
    	return x*w;
    }
    int to[N<<1],nt[N<<1],w[N<<1],hd[N],tot=1;
    void add(int x,int y,int z)
    {
    	++tot,to[tot]=y,nt[tot]=hd[x],w[tot]=z,hd[x]=tot;
    	++tot,to[tot]=x,nt[tot]=hd[y],w[tot]=z,hd[y]=tot;
    }
    int n,ff[N],sz[N],rt,sq[N];
    int findf(int x){return ff[x]==x?x:ff[x]=findf(ff[x]);}
    LL ds[N],mx;
    bool cmp(int aa,int bb){return ds[aa]>ds[bb];}
    void dfs(int x,int ffa,LL de)
    {
    	ds[x]=max(ds[x],de);
    	for(int i=hd[x];i;i=nt[i])
    	{
    		int y=to[i];
    		if(y==ffa) continue;
    		dfs(y,x,de+w[i]);
    	}
    	if(mx<de) mx=de,rt=x;
    }
    
    int main()
    {
        ////////QWQWQ
    	n=rd();
    	for(int i=1;i<n;++i)
    	{
    		int x=rd(),y=rd(),z=rd();
    		add(x,y,z);
    	}
    	mx=0,dfs(1,0,0);
    	int r2=rt;
    	mx=0,dfs(r2,0,0);
    	dfs(rt,0,0);
    	for(int i=1;i<=n;++i) sq[i]=i;
    	sort(sq+1,sq+n+1,cmp);
    	int q=rd();
    	while(q--)
    	{
    		LL lm=rd();
    		for(int i=1;i<=n;++i) ff[i]=i,sz[i]=1;
    		int ans=0;
    		for(int i=1,j=1;i<=n;++i)
    		{
    			int x=sq[i];
    			while(ds[sq[j]]-ds[x]>lm)
    				--sz[findf(sq[j])],++j;
    			for(int i=hd[x];i;i=nt[i])
    			{
    				int y=to[i];
    				if(ds[y]>=ds[x]&&findf(y)!=findf(x))
    					sz[findf(x)]+=sz[findf(y)],ff[findf(y)]=findf(x);
    			}
    			ans=max(ans,sz[findf(x)]);
    		}
    		printf("%d
    ",ans);
    	}
    	return 0;
    }
    
  • 相关阅读:
    家庭内网向导帮助文档
    Nginx 容器连接 php rc-fpm 容器编译 php
    samba 容器实现共享
    编程思想(POP,OOP,SOA,AOP)
    OOP(面向对象编程)
    MySql5.6 Window超详细安装教程
    JAVA设计模式:状态模式
    Mysql设置创建时间字段和更新时间字段自动获取时间,填充时间
    eclipse里新建work set,将项目分组放在不同文件夹
    错误记录
  • 原文地址:https://www.cnblogs.com/smyjr/p/11783152.html
Copyright © 2011-2022 走看看