码迷,mamicode.com
首页 > 其他好文 > 详细

CF516D Drazil and Morning Exercise

时间:2019-11-02 18:20:49      阅读:57      评论:0      收藏:0      [点我收藏+]

标签:pac   并且   ++i   --   一个   tchar   sign   har   its   

cf

luogu

首先每个点到最远点的距离可以预处理出来,这个距离显然是这个点到树直径两端点的最大值.把那个距离记为\(d_i\),然后从小到大枚举\(d_i\),并强制它为最大的\(d_i\),那么前面\(d_j\)更小的,满足\(d_i-d_j\le 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\n",ans);
    }
    return 0;
}

CF516D Drazil and Morning Exercise

标签:pac   并且   ++i   --   一个   tchar   sign   har   its   

原文地址:https://www.cnblogs.com/smyjr/p/11783152.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!