BZOJ5192[Usaco2018 Feb] New Barns

原题链接:https://www.lydsy.com/JudgeOnline/problem.php?id=5192

New Barns

Description

FarmerJohn注意到他的奶牛们如果被关得太紧就容易吵架,所以他想开放一些新的牛棚来分散她们。每当FJ建造一个新牛棚的时候,他会将这个牛棚用至多一条双向道路与一个现有的牛棚连接起来。为了确保他的奶牛们足够分散,他有时想要确定从某个特定的牛棚出发,到它能够到达的最远的牛棚的距离(两个牛棚之间的距离等于从一个牛棚出发到另一个之间必须经过的道路条数)。FJ总共会给出Q(1≤Q≤10^5)次请求,每个请求都是“建造”和“距离”之一。对于一个建造请求,FJ建造一个牛棚,并将其与至多一个现有的牛棚连接起来。对于一个距离请求,FJ向你询问从某个特定的牛棚通过一些道路到离它最远的牛棚的距离。保证询问的牛棚已经被建造。请帮助FJ响应所有的请求。

Input

第一行包含一个整数Q

以下Q行,每行包含一个请求。每个请求的格式都是“B p”或是“Q k”

分别告诉你建造一个牛棚并与牛棚p连接,或是根据定义求从牛棚k出发最远的距离。

如果p=-1,则新的牛棚不会与其他牛棚连接。

否则,p是一个已经建造的牛棚的编号。

牛棚编号从1开始,所以第一个被建造的谷仓是1号谷仓,第二个是2号谷仓,以此类推。

Output

对于每个距离请求输出一行。注意一个没有连接到其他牛棚的牛棚的最远距离为0

Sample Input

7
B -1
Q 1
B 1
B 2
Q 3
B 2
Q 2

Sample Output

0
2
1

输入样例对应下面的牛棚网:

  (1) 

    \   

     (2)---(4)

    /

  (3)

对于请求1,我们建造牛棚1。对于请求2,我们询问从1出发到最远连接的牛棚的距离。由于牛棚1没有与其他牛棚连接,所以回答是0。对于请求3,我们建造牛棚2并将其与牛棚1连接。对于请求4,我们建造牛棚3并将其与牛棚2连接。对于请求5,我们询问从3出发到最远连接的牛棚的距离。在这时,最远的是牛棚1,距离为2单位。对于请求6,我们建造牛棚4并将其与牛棚2连接。对于请求7,我们询问从2出发到最远连接的牛棚的距离。所有其他三个牛棚1,3,4都与2相距相同的距离1,所以这就是我们的回答。

题解

大力 L C T 维护树的直径

LCT天下第一!!!!

代码
#include<bits/stdc++.h>
#define ls son[v][0]
#define rs son[v][1]
using namespace std;
const int M=1e5+5;
int dad[M],son[M][2],sum[M],le[M],ri[M],f[M],q,tot;
char ch[5];
bool rev[M];
bool notroot(int v){return son[dad[v]][0]==v||son[dad[v]][1]==v;}
void up(int v){sum[v]=sum[ls]+sum[rs]+1;}
void turn(int v){swap(ls,rs);rev[v]^=1;}
void push(int v){if(!rev[v])return;if(ls)turn(ls);if(rs)turn(rs);rev[v]=0;}
void down(int v){if(notroot(v))down(dad[v]);push(v);}
void spin(int v)
{
    int f=dad[v],ff=dad[f],k=son[f][1]==v,w=son[v][!k];
    if(notroot(f))son[ff][son[ff][1]==f]=v;son[v][!k]=f,son[f][k]=w;
    if(w)dad[w]=f;dad[f]=v,dad[v]=ff;
    up(f);
}
void splay(int v)
{
    down(v);int f,ff;
    while(notroot(v))
    {
        f=dad[v],ff=dad[f];
        if(notroot(f))spin((son[f][0]==v)^(son[ff][0]==f)?v:f);
        spin(v);
    }
    up(v);
}
void access(int v){for(int f=0;v;v=dad[f=v])splay(v),rs=f,up(v);}
void beroot(int v){access(v),splay(v),turn(v);}
void link(int x,int y){splay(x),dad[x]=y;}
int dis(int x,int y){beroot(x),access(y),splay(y);return sum[y]-1;}
int find(int v){return f[v]==v?v:f[v]=find(f[v]);}
void in(){scanf("%d",&q);}
void ac()
{
    int x,l1,l2,l3;
    while(q--)
    {
        scanf("%s%d",ch,&x);
        if(ch[0]=='B')
        {
            ++tot;
            if(x==-1)f[tot]=le[tot]=ri[tot]=tot;
            else
            {
                link(tot,x);x=f[tot]=find(x);
                l1=dis(tot,le[x]),l2=dis(tot,ri[x]),l3=dis(le[x],ri[x]);
                if(l1>=l2&&l1>=l3)ri[x]=tot;else if(l2>=l1&&l2>=l3)le[x]=tot;
            }
        }
        else l1=find(x),printf("%d\n",max(dis(le[l1],x),dis(ri[l1],x)));
    }
}
int main(){in();ac();}

猜你喜欢

转载自blog.csdn.net/shadypi/article/details/81170899