zoukankan      html  css  js  c++  java
  • 【bzoj3631】[JLOI2014]松鼠的新家

    题目大意就是按照他给的顺序遍历树,问每个节点会经过几次,最后的那个要减1

    类似前缀和的思想 

    从起点x到终点y,只需给x,y两个结点加1,给LCA(x,y),fa[LCA(x,y)]减1,最后做一次从底到根的递推即可求出每个点在多少条链上 

    #include<algorithm>
    #include<iostream>
    #include<cstdlib>
    #include<cstring>
    #include<cstdio>
    #include<cmath>
    #include<queue>
    using namespace std;
     
    typedef long long LL;
     
    #define N 300010
     
    struct edge
    {
        int to,next;
    }e[N<<2];
    int head[N<<2];
    int cnt;
     
    int n;
    int id;
    int x,y;
     
    int a[N],ans[N];
    int siz[N],dep[N],fa[N],top[N],son[N],dfn[N];
     
    inline int getint()
    {
        int x=0,f=1;char ch=getchar();
        while (ch>'9' || ch<'0') {if (ch=='-') f=-1;ch=getchar();}
        while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
     
    void link(int x,int y)
    {
        e[++cnt]=(edge){y,head[x]};
        head[x]=cnt;
    }
     
    void dfs(int x)
    {
        siz[x]=1;
        son[x]=0;
        dfn[++id]=x;
        for (int i=head[x];i;i=e[i].next)
        {
            int v=e[i].to;
            if (fa[x]!=v)
            {
                fa[v]=x;
                dep[v]=dep[x]+1;
                dfs(v);
                siz[x]+=siz[v];
                if (siz[v]>siz[son[x]])
                    son[x]=v;
            }
        }
    }
     
    void dfs2(int x,int d)
    {
        top[x]=d;
        if (son[x])
            dfs2(son[x],d);
        for (int i=head[x];i;i=e[i].next)
        {
            int v=e[i].to;
            if (fa[x]!=v && son[x]!=v)
                dfs2(v,v);
        }
    }
     
    int lca(int x,int y)
    {
        while (top[x]!=top[y])
        {
            int a=top[x];
            int b=top[y];
            if (dep[a]<dep[b])
                swap(a,b),swap(x,y);
            x=fa[top[x]];
        }
        return dep[x]<dep[y] ? x : y;
    }
     
    int main()
    {
        n=getint();
        for (int i=1;i<=n;i++)
            a[i]=getint();
        for (int i=1;i<n;i++)
        {
            x=getint();
            y=getint();
            link(x,y);
            link(y,x);
        }
        dfs(1);
        dfs2(1,1);
        for (int i=2;i<=n;i++)
        {
            int u=a[i-1],v=a[i],w=lca(u,v);
            ans[u]++;
            ans[v]++;
            ans[w]--;
            ans[fa[w]]--;
        }
        for (int i=n;i>=1;i--)
            ans[fa[dfn[i]]]+=ans[dfn[i]];
        for (int i=1;i<=n;i++)
            if (a[1]!=i)
                printf("%d
    ",ans[i]-1);
            else
                printf("%d
    ",ans[i]);
        return 0;
    }
    

      

  • 相关阅读:
    关于Update语句在不同数据库中的差别
    MSIL指令速查表
    一个对于博客园的建议
    代码风格关于if语句
    关于Page.cs文件中注释的一点补充
    在Java、C#和C++中遍历集合
    BPEL4WS的开源Java实现
    【Linux】linux固定ip
    【Linux】【MySQL】MySQL主从数据库
    wpf 写个简单的控件吧
  • 原文地址:https://www.cnblogs.com/yangjiyuan/p/5503196.html
Copyright © 2011-2022 走看看