zoukankan      html  css  js  c++  java
  • CF379F New Year Tree (树的直径)

    CF379F New Year Tree

    分析:

    树的直径就是每次求树中最远的两个点。

    在一棵树上快速计算两两点之间的距离,可以用倍增

    设现在树上最远的两个点为L和R。

    若在u处加两个点,直径会+1或者不改变。

    对这两个点求一下到L的距离,和到R的距离,看会不会使答案更优,如果使得答案更优,就把L,或R更新成目前的节点。

    对于动态加点,直接对新加的点跑倍增即可。

    #include<bits/stdc++.h>
    using namespace std;
    #define N 1000005
    #define ri register int
    int q,dep[N],fa[N][22],L,R,ans,cnt;
    vector<int> e[N];
    void init()
    {
        fa[2][0]=fa[3][0]=fa[4][0]=1;
        dep[2]=dep[3]=dep[4]=1;
        ans=2; L=2,R=3; cnt=4;
    }
    void work(int u,int ff)
    {
        fa[u][0]=ff; dep[u]=dep[ff]+1;
        for(ri i=1;i<=20;++i) fa[u][i]=fa[fa[u][i-1]][i-1];
    }
    int lca(int x,int y)
    {
        if(dep[x]<dep[y]) swap(x,y);
        int ret=0;
        for(ri i=20;i>=0;--i) if(dep[fa[x][i]]>=dep[y]) x=fa[x][i],ret+=(1<<i);
        if(x==y) return ret;
        for(ri i=20;i>=0;--i) if(fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i],ret+=(1<<(i+1));
        return ret+2;
    }
    int main()
    {
        init();
        int q;
        scanf("%d",&q);
        while(q--){
            int x;
            scanf("%d",&x);
            e[x].push_back(++cnt); work(cnt,x);
            e[x].push_back(++cnt); work(cnt,x);
            int lc1=lca(x,L),lc2=lca(x,R);
            if(lc1+1<=ans && lc2+1<=ans) printf("%d
    ",ans);
            else if(lc1+1>ans && lc2<lc1) ans=lc1+1,R=cnt,printf("%d
    ",ans);
            else ans=lc2+1,L=cnt,printf("%d
    ",ans); 
        }
    } 
    /*
    5
    3
    5
    6
    10
    7
    10
    4
    6
    7
    9
    5
    */
    View Code
  • 相关阅读:
    基于Andoird 4.2.2的同步框架源代码学习——同步发起端
    C#MD5为密码加密
    YOUYOU深入学习Ganglia之三(gmetad的软件架构)
    js原生appendChild的bug
    Spring MVC 教程,快速入门,深入分析
    Centos 6.4 Linux 相关问题总结
    jQuery插件之-瀑布流插件
    编辑简单的 shell程序
    Qt国际化相关类
    三层架构与MVC
  • 原文地址:https://www.cnblogs.com/mowanying/p/11838379.html
Copyright © 2011-2022 走看看