zoukankan      html  css  js  c++  java
  • luogu P4183 [USACO18JAN]Cow at Large P

    传送门

    首先考虑N^2做法,每次从一个点出发,如果到达一个点,然后到达这个点的时间(le)离这个点最近的叶子距离(di_x),那么答案+1,否则继续找点

    这个暴力很不好优化.可以这样认为,如果某个点贡献答案,那么子树里的点也要贡献答案(某个点走不下去,那么走子树内的点也走不下去,也符合条件),不过一个子树一共只贡献1.可以发现一个子树度数和(sum deg_i),加上1为子树大小*2,即(sum 2-deg_i=1),所以单次询问的答案就是所有符合条件的点的(2-deg_i)之和

    现在考虑每个点对(x,y),y对x的贡献,要满足(dis_{x,y}le di_y).考虑点分治,那么记某个点到分治重心距离为(dep_x),那么对x造成贡献的点y要满足(dep_x+dep_yle di_y),即(dep_xle di_y-dep_y),那么这个可以树状数组快速算贡献

    // luogu-judger-enable-o2
    #include<bits/stdc++.h>
    #define LL long long
    #define uLL unsigned long long
    #define il inline
    #define re register
    
    using namespace std;
    const int N=7e4+10;
    il int rd()
    {
        int 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],hd[N],dg[N],tot=1;
    il void add(int x,int y)
    {
        ++tot,to[tot]=y,nt[tot]=hd[x],hd[x]=tot,++dg[x];
        ++tot,to[tot]=x,nt[tot]=hd[y],hd[y]=tot,++dg[y];
    }
    int n,fa[N],dd[N];
    void dfs1(int x)
    {
        dd[x]=dg[x]==1?0:n+1;
        for(int i=hd[x];i;i=nt[i])
        {
            int y=to[i];
            if(y!=fa[x])
            {
                fa[y]=x,dfs1(y);
                if(dd[x]>dd[y]+1) dd[x]=dd[y]+1;
            }
        }
    }
    void dfs2(int x)
    {
        for(int i=hd[x];i;i=nt[i])
        {
            int y=to[i];
            if(y!=fa[x])
            {
                if(dd[y]>dd[x]+1) dd[y]=dd[x]+1;
                dfs2(y);
            }
        }
    }
    int c[N<<1];
    il void ad(int x,int y){while(x<=n+n) c[x]+=y,x+=x&(-x);}
    il int gsm(int x){int an=0;while(x) an+=c[x],x-=x&(-x);return an;}
    bool ban[N];
    int sz[N],size,rt,rsz,st[N][2],tp,an[N];
    void grt(int x,int ffa)
    {
        sz[x]=1;
        int ma=0;
        for(int i=hd[x];i;i=nt[i])
        {
            int y=to[i];
            if(y!=ffa&&!ban[y])
            {
                grt(y,x),sz[x]+=sz[y];
                ma=max(ma,sz[y]);
            }
        }
        ma=max(ma,size-sz[x]);
        if(ma<rsz) rsz=ma,rt=x;
    }
    void dfs3(int x,int ffa,int de)
    {
        st[++tp][0]=de,st[tp][1]=x;
        for(int i=hd[x];i;i=nt[i])
        {
            int y=to[i];
            if(y!=ffa&&!ban[y]) dfs3(y,x,de+1);
        }
    }
    void cal(int x,int ffa,int op)
    {
        tp=0,dfs3(x,ffa,ffa>0);
        for(int i=1;i<=tp;++i) ad(dd[st[i][1]]-st[i][0]+n,2-dg[st[i][1]]);
        for(int i=1;i<=tp;++i) an[st[i][1]]+=op*gsm(st[i][0]+n);
        for(int i=1;i<=tp;++i) ad(dd[st[i][1]]-st[i][0]+n,-(2-dg[st[i][1]]));
    }
    void sov(int x)
    {
        rt=0,rsz=size,grt(x,0);
        x=rt;
        cal(x,0,1),ban[x]=1;
        for(int i=hd[x];i;i=nt[i])
            if(!ban[to[i]])
            {
                int y=to[i];
                cal(y,x,-1);
                size=sz[y],sov(y);
            }
    }
    
    
    int main()
    {
        n=rd();
        for(int i=1;i<n;++i) add(rd(),rd());
        dfs1(1),dfs2(1);
        size=n,sov(1);
        for(int i=1;i<=n;++i) printf("%d
    ",dd[i]?an[i]:1);
        return 0;
    }
    
  • 相关阅读:
    linux oracle命令行窗口命令上下翻阅
    oracle 转移表空间
    perl字符集处理
    Perl解析JSON数据精解
    处理外壳PROC
    FileIsExe
    写壳前的设计
    SEH结构化异常处理03
    SEH结构化异常处理02
    博客首记
  • 原文地址:https://www.cnblogs.com/smyjr/p/10274716.html
Copyright © 2011-2022 走看看