CF516D Drazil and Morning Exercise

Posted smyjr

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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;
}

以上是关于CF516D Drazil and Morning Exercise的主要内容,如果未能解决你的问题,请参考以下文章

CF516DDrazil and Morning Exercise

CF516D

Cf #292 DDrazil and Morning Exercise(树的直径,树上差分)

Codeforce 515A - Drazil and Date

CF R631 div2 1330 E Drazil Likes Heap

[codeforces 516]A. Drazil and Factorial