• CF516D Drazil and Morning Exercise


    (color{#FF003F}{ exttt {CF516D Drazil and Morning Exercise}})

    (f_x=max_{i=1}^{n}dist(x,i))
    所有的 (f_x) 可以换根dp求出。

    问题转化成了:树上点有权值, (q) 次询问,给出 (L) ,求满足 (max_{i in S}f_i-min_{i in S}f_i leq L)(S) 中最大的集合大小。
    一种想法是每条边都有出现时间区间,线段树分治维护,复杂度 (O(nq log n alpha(n))) ,看起来很大的样子。

    考虑 (f_i) 的性质,如果把 (f_i) 最小的点作为根,(forall u=fa_v , f_v=f_u+w(u,v))

    证明:

    (g_i) 表示只考虑 (i) 子树中的点时的 (max dist(x,i)) ,有 (f_i geq g_i)

    首先先证 如果 (u)(f_i) 最小的点,(v)(u) 的儿子,那么 (f_v=f_u+w(u,v))

    假设 (f_v)(v) 子树内一点 (x) 转移,即 (f_v=g_v=g_x+w(x,v)),那么(f_u geq g_v+w(u,v) geq f_v),与 (u)(f_i) 最小的点矛盾,所以 (f_v=f_u+w(u,v))

    由上可知 (f_v=f_u+w(u,v) geq g_x+w(v,x)) ,那就有 (f_u+w(u,v)+w(v,x) > g_x),那么 (f_x=f_u+w(u,v)+w(v,x)=f_v+w(v,x))
    归纳一下就可知 (forall u=fa_v , f_v=f_u+w(u,v))

    把所有点按 (f_i) 从大到小的顺序加入,并查集维护下就行了。(O(n log n+nqalpha(n)))

    // Author -- Frame
    
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<cstdlib>
    #include<algorithm>
    #include<vector>
    #include<iostream>
    
    #define lowbit(x) ((x)&(-x))
    #define Finline __inline__ __attribute__ ((always_inline))
    #define DEBUG fprintf(stderr,"Running on Line %d in Function %s
    ",__LINE__,__FUNCTION__)
    
    typedef long long ll;
    typedef unsigned int uint;
    typedef unsigned long long ull;
    
    const int inf=0x3f3f3f3f,Inf=0x7fffffff;
    const ll INF=0x7fffffffffffffff;
    const double eps=1e-10;
    
    template <typename _Tp>_Tp gcd(const _Tp &a,const _Tp &b){return (!b)?a:gcd(b,a%b);}
    template <typename _Tp>Finline _Tp abs(const _Tp &a){return a>=0?a:-a;}
    template <typename _Tp>Finline _Tp max(const _Tp &a,const _Tp &b){return a<b?b:a;}
    template <typename _Tp>Finline _Tp min(const _Tp &a,const _Tp &b){return a<b?a:b;}
    template <typename _Tp>Finline void chmax(_Tp &a,const _Tp &b){(a<b)&&(a=b);}
    template <typename _Tp>Finline void chmin(_Tp &a,const _Tp &b){(b<a)&&(a=b);}
    template <typename _Tp>Finline bool _cmp(const _Tp &a,const _Tp &b){return abs(a-b)<=eps;}
    template <typename _Tp>Finline void read(_Tp &x)
    {
    	register char ch(getchar());
    	bool f(false);
    	while(ch<48||ch>57) f|=ch==45,ch=getchar();
    	x=ch&15,ch=getchar();
    	while(ch>=48&&ch<=57) x=(((x<<2)+x)<<1)+(ch&15),ch=getchar();
    	if(f) x=-x;
    }
    template <typename _Tp,typename... Args>Finline void read(_Tp &t,Args &...args)
    {
    	read(t);read(args...);
    }
    Finline int read_str(char *s)
    {
    	register char ch(getchar());
    	while(ch==' '||ch=='
    '||ch=='
    ') ch=getchar();
    	register char *tar=s;
    	*tar=ch,ch=getchar();
    	while(ch!=' '&&ch!='
    '&&ch!='
    '&&ch!=EOF) *(++tar)=ch,ch=getchar();
    	return tar-s+1;
    }
    
    const int N=100005;
    struct edge{
    	int v,nxt,w;
    }c[N<<1];
    int front[N],cnt_;
    Finline void add(int u,int v,int w)
    {
    	c[++cnt_]=(edge){v,front[u],w},front[u]=cnt_;
    }
    ll dp1[N],dp2[N],f[N];
    void dfs1(int x,int fa)
    {	
    	dp1[x]=0;
    	for(int i=front[x];i;i=c[i].nxt)
    	{
    		if(c[i].v!=fa)
    		{
    			dfs1(c[i].v,x);
    			if(dp1[c[i].v]+c[i].w>dp1[x])
    			{
    				dp2[x]=dp1[x];
    				dp1[x]=dp1[c[i].v]+c[i].w;
    			}
    			else if(dp1[c[i].v]+c[i].w>dp2[x])
    			{
    				dp2[x]=dp1[c[i].v]+c[i].w;
    			}
    		}
    	}
    }
    void dfs2(int x,int fa,int val)
    {
    	if(fa)
    	{
    		ll tmp;
    		if(dp1[fa]==dp1[x]+val)
    		{
    			tmp=dp2[fa];
    		}
    		else
    		{
    			tmp=dp1[fa];
    		}
    		tmp+=val;
    		if(tmp>dp1[x])
    		{
    			dp2[x]=dp1[x];
    			dp1[x]=tmp;
    		}
    		else if(tmp>dp2[x])
    		{
    			dp2[x]=tmp;
    		}
    	}
    	for(int i=front[x];i;i=c[i].nxt)
    	{
    		if(c[i].v!=fa)
    		{
    			dfs2(c[i].v,x,c[i].w);
    		}
    	}
    }
    int a[N];
    int fa[N],siz[N];
    int find(int x){return x==fa[x]?x:fa[x]=find(fa[x]);}
    int maxx;
    int cnt[N];
    void merge(int a,int b)
    {
    	a=find(a);
    	b=find(b);
    	--cnt[siz[b]];
    	--cnt[siz[a]];
    	if(siz[a]>siz[b])
    	{
    		fa[b]=a;
    		siz[a]+=siz[b];
    		++cnt[siz[a]];
    		chmax(maxx,siz[a]);
    	}
    	else
    	{
    		fa[a]=b;
    		siz[b]+=siz[a];
    		++cnt[siz[b]];
    		chmax(maxx,siz[b]);
    	}
    }
    void dec(int x)
    {
    	x=find(x);
    	--cnt[siz[x]];
    	--siz[x];
    	++cnt[siz[x]];
    	if(!cnt[maxx]) --maxx;
    }
    bool used[N];
    int main()
    {
    	int n;
    	read(n);
    	int x,y,z;
    	for(int i=1;i<n;++i)
    	{
    		read(x,y,z);
    		add(x,y,z),add(y,x,z);
    	}
    	dfs1(1,0);
    	dfs2(1,0,0);
    	for(int i=1;i<=n;++i) f[i]=dp1[i],a[i]=i;
    	std::sort(a+1,a+n+1,[](const int &a,const int &b)->bool{return f[a]>f[b];});
    	int _;
    	read(_);
    	ll L;
    	while(_--)
    	{
    		read(L);
    		for(int i=1;i<=n;++i)
    		{
    			fa[i]=i;
    			siz[i]=1;
    			used[i]=false;
    			cnt[i]=0;
    		}
    		cnt[1]=n;
    		maxx=1;
    		int pos=1;
    		int ans=0;
    		for(int i=1;i<=n;++i)
    		{
    			for(int _=front[a[i]];_;_=c[_].nxt)
    			{
    				if(used[c[_].v])
    				{
    					merge(a[i],c[_].v);
    				}
    			}
    			used[a[i]]=true;
    			while(pos<=n&&f[a[pos]]-f[a[i]]>L)
    			{
    				dec(a[pos]);
    				++pos;
    			}
    			chmax(ans,maxx);
    		}
    		printf("%d
    ",ans);
    	}
    	return 0;
    }
    
  • 相关阅读:
    网络通讯协议的基本要素
    java实现二维码的生成与解析
    SpringCloud应用间通信-RestTemplate与Feign
    SpringCloud服务注册与发现-Eureka、Nacos和Consul
    极光推送-java消息推送app
    Git的回滚和撤销操作
    SOFABoot学习
    记录一次生产环境下EleasticSearch故障(cpu打满)
    记录SQL优化
    利用二进制存储多种状态
  • 原文地址:https://www.cnblogs.com/Frame233/p/12529484.html
Copyright © 2020-2023  润新知