bzoj2002: [Hnoi2010]Bounce 弹飞绵羊

【题意】

  给出n个点,每个点都会指向它后方的一个点,显然最后都指向一个不存在的点。把最后一个点当作根拎起来就是一棵树了。询问中,某一个点指向的点随时会变,显然就是要你支持动态改变树的结构。然后又会不时的询问一个点到根的距离。

【题解】

  又是lct裸题,注意 维护splay的信息 和 传递标记。。。。。。

  其它的细节网上题解一大堆就不多述了。。。。。。

  一开始写lct真的好艰辛。。。

【代码】

#include <iostream>
#include <cstdio>
using namespace std;
const int N=200005;
int size[N],c[N][2],rev[N],fa[N],pre[N],a[N];
int n,x,y,Q;
void read(int &x)
{
    x=0;char ch;int sign=1;
    do{ch=getchar();if(ch=='-')sign*=-1;}while (ch<'0' || ch>'9');
    do{x=x*10+ch-48;ch=getchar();}while (ch>='0' && ch<='9');
    x*=sign;
}
bool isroot(int x)
{
    return c[fa[x]][0]!=x && c[fa[x]][1]!=x;
}
void up(int x)
{
    size[x]=size[c[x][0]]+size[c[x][1]]+1;
}
void down(int x)
{ 
    if (rev[x])
    {
        rev[x]=0;        
        swap(c[x][0],c[x][1]);
        rev[c[x][0]]^=1,rev[c[x][1]]^=1;
    }
}
void rotate(int x)
{    
    int y=fa[x],z=fa[y],l,r;    
    if (c[y][0]==x)    l=0;else l=1;r=1^l;
    if (!isroot(y))    if (c[z][0]==y)    c[z][0]=x;else c[z][1]=x;
    fa[x]=z;
     c[y][l]=c[x][r];fa[c[x][r]]=y;
    c[x][r]=y;fa[y]=x;
     up(y);up(x);
} 
void splay(int x)
{
    int cnt=0,y=x,z;    
    while (!isroot(y))
    {
        a[++cnt]=y;
        y=fa[y];
    }
    a[++cnt]=y;
    while (cnt--)    down(a[cnt+1]);
    while (!isroot(x))
    {
        y=fa[x];z=fa[y];
        if (!isroot(y))
            if (c[y][0]==x ^ c[z][0]==y)
                rotate(x);
            else rotate(y);
        rotate(x);
    }
}
void access(int x)
{
    int t=0; 
    while (x)
    {
        splay(x);
        c[x][1]=t;
        t=x;x=fa[x];
    }
}
void mt(int x)
{
    access(x);
    splay(x);
}
void make_root(int x)
{
    mt(x);
     rev[x]^=1;
    down(x);
}
void link(int x,int y)
{
    make_root(x);
    fa[x]=y;    
}
void cut(int x,int y)
{
    make_root(x);
    mt(y);
    fa[x]=c[y][0]=0;
    up(y);
}
int solve(int x)
{
    make_root(n+1);
    mt(x);
    return size[c[x][0]];
}
int main()
{
    read(n);
    for (int i=1;i<=n;++i)
    {
        size[i]=1;
        read(pre[i]);
        pre[i]+=i;
        if (pre[i]>n)
            pre[i]=n+1;
        link(i,pre[i]);
    }
    read(Q);
    while (Q--)
    {
        read(x);
        if (x==1)
        {
            read(y);
            ++y;
            printf("%d\n",solve(y));
        }
        else
        {
            read(x);read(y);
            ++x;
            cut(x,pre[x]);
            y=x+y;
            if (y>n)    y=n+1;
            link(x,pre[x]=y);
        }
    }
    return 0;
}
View Code

 

posted @ 2017-09-19 21:17 Bleacher 阅读(...) 评论(...) 编辑 收藏