zoukankan      html  css  js  c++  java
  • 【BZOJ4543】Hotel加强版(长链剖分)

    【BZOJ4543】Hotel加强版(长链剖分)

    题面

    BZOJ,没有题面
    洛谷,只是普通版本

    题解

    原来我们的(O(n^2))做法是设(f[i][j])表示以(i)为根的子树中,距离(i)的深度为(j)的点的个数,这样子可以每次在(LCA)处合并答案。
    然后长链剖分优化一下,就变成了(O(n))的???
    写的详细写的题解
    玄学的指针我也没太懂啊。。。。我才不会说我代码是照着题解打的

    upd:之前的代码蒯错了,我去BZOJ把过了的代码再蒯一遍

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    #define ll long long
    #define MAX 100100
    inline int read()
    {
        int x=0,t=1;char ch=getchar();
        while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
        if(ch=='-')t=-1,ch=getchar();
        while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
        return x*t;
    }
    struct Line{int v,next;}e[MAX<<1];
    int h[MAX],cnt=1,n;
    inline void Add(int u,int v){e[cnt]=(Line){v,h[u]};h[u]=cnt++;}
    int dep[MAX],hson[MAX],md[MAX];
    void dfs1(int u,int ff)
    {
        for(int i=h[u];i;i=e[i].next)
        {
            int v=e[i].v;if(v==ff)continue;
            dfs1(v,u);md[u]=max(md[u],md[v]);
            if(md[v]>md[hson[u]])hson[u]=v;
        }
        md[u]=md[hson[u]]+1;
    }
    ll *f[MAX],*g[MAX],tmp[MAX<<2],*id=tmp,ans;
    void dfs(int u,int ff)
    {
        if(hson[u])f[hson[u]]=f[u]+1,g[hson[u]]=g[u]-1,dfs(hson[u],u);
        f[u][0]=1;ans+=g[u][0];
        for(int i=h[u];i;i=e[i].next)
        {
            int v=e[i].v;if(v==ff||v==hson[u])continue;
            f[v]=id;id+=md[v]<<1;g[v]=id;id+=md[v]<<1;
            dfs(v,u);
            for(int j=0;j<md[v];++j)
            {
                if(j)ans+=f[u][j-1]*g[v][j];
                ans+=g[u][j+1]*f[v][j];
            }
            for(int j=0;j<md[v];++j)
            {
                g[u][j+1]+=f[u][j+1]*f[v][j];
                if(j)g[u][j-1]+=g[v][j];
                f[u][j+1]+=f[v][j];
            }
        }
    }
    int main()
    {
        n=read();
        for(int i=1,u,v;i<n;++i)u=read(),v=read(),Add(u,v),Add(v,u);
        dfs1(1,0);f[1]=id;id+=md[1]<<1;g[1]=id;id+=md[1]<<1;
        dfs(1,0);printf("%lld
    ",ans);
        return 0;
    }
    
  • 相关阅读:
    1041. 困于环中的机器人
    95. 不同的二叉搜索树 II
    LeetCode945:使数组唯一的最小增量
    LeetCode:925.长按键入
    LeetCode:926. 将字符串翻转到单调递增
    InteliJ 安装PlantUML插件
    CodeBlock换肤
    正则表达式验证手机号和座机号
    C#中使用反射遍历一个对象属性和值以及百分数
    c#中@的用法
  • 原文地址:https://www.cnblogs.com/cjyyb/p/9464994.html
Copyright © 2011-2022 走看看