zoukankan      html  css  js  c++  java
  • codeforces 379F-New Year Tree

    传送门:QAQQAQ

    题意:原始有一棵根为1,有三个叶子2,3,4的树。有n个操作,每次可以在一个叶子下面续上两个节点,每次操作完问当前树的直径。

    思路:先预处理出树的直径,以及其中一条直径两端的点l,r,对于新加的点,只需计算其与两端的距离(倍增LCA),若大于ans,则更新直径l或r,否则就不变

    证明:假设加上点x后直径长为ans+1,因为x仅有一条边连它的父亲f,所以从f出发最远点距离为ans,即没加上点x前f为其中一条直径的端点。

               因为各个直径两两相交(否则定可以在上方找到一条把两直径连起来,使直径更长),两直径前后两端不同区间一样长,所以从f出发到l,r定有一个距离为ans,所以这样的更新是没有反例的

    补:树的直径dfs方法证明

    1    设u为s-t路径上的一点,结论显然成立,否则设搜到的最远点为T(往下走)则

    dis(u,T) >dis(u,s)     且  dis(u,T)>dis(u,t)   则最长路不是s-t了,与假设矛盾

    2   设u不为s-t路径上的点

        首先明确,假如u走到了s-t路径上的一点,那么接下来的路径肯定都在s-t上了,而且终点为s或t,在1中已经证明过了

        所以现在又有两种情况了:

        1:u走到了s-t路径上的某点,假设为X,最后肯定走到某个端点,假设是t ,则路径总长度为dis(u,X)+dis(X,t)

        2:u走到最远点的路径u-T与s-t无交点,则dis(u,T) >dis(u,X)+dis(X,t);显然,如果这个式子成立,

        则dis(s,X)+dis(X,u)+dis(u,T)>dis(s,X)+dis(X,t)=dis(s,t)  即dis(s,T)>dis(s,t) 最长路不是s-t矛盾    (摘自https://blog.csdn.net/frankax/article/details/79514778)

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef long long ll;
     4 const int inf=(int)(2e9);
     5 const ll INF=(ll)(5e18);
     6 const int N=1000010;//pay attention to the size of the array!!!
     7 const int M=30;
     8 
     9 int n,l,r,num,ans;
    10 int father[N][30],d[N];
    11 vector<int> v[N];
    12 
    13 void add_edge(int x,int y)
    14 {
    15     v[x].push_back(y);
    16     father[y][0]=x;
    17     for(int i=1;i<M;i++) father[y][i]=father[father[y][i-1]][i-1];
    18     d[y]=d[x]+1;
    19 }
    20 
    21 void init()
    22 {
    23     num=5;
    24     memset(father,0,sizeof(father));
    25     for(int i=0;i<M;i++) father[1][i]=1;
    26     d[1]=0; d[2]=d[3]=d[4]=1;
    27 }
    28 
    29 int LCA(int x,int y)
    30 {
    31     if(d[x]<d[y]) swap(x,y);
    32     int dst=d[x]-d[y];
    33     for(int i=M-1;i>=0;i--)
    34     {
    35         int tmp=(1<<i);
    36         if(tmp<=dst)
    37         {
    38             dst-=tmp;
    39             x=father[x][i];
    40         }
    41     }
    42     for(int i=M-1;i>=0;i--)
    43     {
    44         if(father[x][i]==father[y][i]) continue;
    45         x=father[x][i]; y=father[y][i];
    46     }
    47     return father[x][0];
    48 }
    49 
    50 int dis(int x,int y)
    51 {
    52     if(x==y) return 0;
    53     int f=LCA(x,y);
    54     return d[x]+d[y]-d[f]*2;
    55 }
    56 
    57 void solve(int x)
    58 {
    59     if(dis(x,l)>ans)
    60     {
    61         ans=dis(x,l);
    62         r=x;//don't confuse the order of l&r
    63     }
    64     if(dis(x,r)>ans) 
    65     {
    66         ans=dis(x,r);
    67         l=x;
    68     }
    69 }
    70 
    71 int main()
    72 {
    73     scanf("%d",&n);
    74     init();
    75     for(int i=2;i<=4;i++)
    76     {
    77         add_edge(1,i);
    78     }
    79     l=2,r=4,ans=2;
    80     while(n--)
    81     {
    82         int x;
    83         scanf("%d",&x);
    84         add_edge(x,num);
    85         add_edge(x,num+1); 
    86         solve(num); 
    87         num+=2;
    88         printf("%d
    ",ans);
    89     }
    90     return 0;
    91 }
    View Code
  • 相关阅读:
    /etc/sysctl.conf 控制内核相关配置文件
    python 并发编程 非阻塞IO模型
    python 并发编程 多路复用IO模型
    python 并发编程 异步IO模型
    python 并发编程 阻塞IO模型
    python 并发编程 基于gevent模块 协程池 实现并发的套接字通信
    python 并发编程 基于gevent模块实现并发的套接字通信
    python 并发编程 io模型 目录
    python 并发编程 socket 服务端 客户端 阻塞io行为
    python 并发编程 IO模型介绍
  • 原文地址:https://www.cnblogs.com/Forever-666/p/10660239.html
Copyright © 2011-2022 走看看