【题解】Luogu P3203 [HNOI2010]弹飞绵羊

原题传送门

预处理:从一个点弹到另一个点就在lct里从\(i\)连边到\(i+k_i\),如果绵羊被弹飞了就从\(i\)连边到\(n+1\)(一个虚拟点,方便统计)

操作1:split(x,n+1),把x到n+1路径上的点放到同一个Splay中,答案就是T.size[n+1]-1

操作2:先把\(i\)\(i+oldk\)的边删除

如果\(i+newk<=n\),从\(i\)连边到\(i+newk\),否则就从\(i\)连边到\(n+1\)

注意:编号是0~n-1,为了方便写码,把所有的编号加1

#include <bits/stdc++.h>
#define N 200005
#define getchar nc
using namespace std;
inline char nc(){
    static char buf[100000],*p1=buf,*p2=buf; 
    return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++; 
}
inline int read()
{
    register int x=0,f=1;register char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
    return x*f;
}
inline void write(register int x)
{
    if(!x)putchar('0');if(x<0)x=-x,putchar('-');
    static int sta[20];register int tot=0;
    while(x)sta[tot++]=x%10,x/=10;
    while(tot)putchar(sta[--tot]+48);
}
inline void Swap(register int &a,register int &b)
{
    a^=b^=a^=b;
}
struct Link_Cut_Tree{
    int c[N][2],fa[N],top,q[N],rev[N],size[N];
    inline void pushup(register int x)
    {
        size[x]=size[c[x][0]]+size[c[x][1]]+1;
    }
    inline void pushdown(register int x){
        if(rev[x])
        {
            register int l=c[x][0],r=c[x][1];
            rev[l]^=1,rev[r]^=1,rev[x]^=1;
            Swap(c[x][0],c[x][1]);
        }
    }
    inline bool isroot(register int x)
    {
        return c[fa[x]][0]!=x&&c[fa[x]][1]!=x;
    }
    inline void rotate(register int x)
    {
        int y=fa[x],z=fa[y],l,r;
        l=c[y][0]==x?0:1;
        r=l^1;
        if(!isroot(y))
            c[z][c[z][0]==y?0:1]=x;
        fa[x]=z;
        fa[y]=x;
        fa[c[x][r]]=y;
        c[y][l]=c[x][r];
        c[x][r]=y;
        pushup(y),pushup(x);
    }
    inline void splay(register int x)
    {
        top=1;
        q[top]=x;
        for(register int i=x;!isroot(i);i=fa[i])
            q[++top]=fa[i];
        for(register int i=top;i;--i)
            pushdown(q[i]);
        while(!isroot(x))
        {
            int y=fa[x],z=fa[y];
            if(!isroot(y))
                rotate((c[y][0]==x)^(c[z][0]==y)?(x):(y));
            rotate(x);
        }
    }
    inline void access(register int x)
    {
        for(register int t=0;x;t=x,x=fa[x])
        {
            splay(x);
            c[x][1]=t;
            pushup(x);	
        }
    }
    inline void makeroot(register int x)
    {
        access(x);
        splay(x);
        rev[x]^=1;
    }
    inline void split(register int x,register int y)
    {
        makeroot(x);
        access(y);
        splay(y);
    }
    inline void cut(register int x,register int y)
    {
        split(x,y);
        if(c[y][0]==x)
        {
            c[y][0]=0;
            fa[x]=0;
        }
    }
    inline void link(register int x,register int y)
    {
        makeroot(x);
        fa[x]=y;
    }
}T;
int n,m,val[N];
int main()
{
    n=read();
    for(register int i=1;i<=n;++i)
    {
        val[i]=read();
        T.link(i,i+val[i]<=n?(i+val[i]):(n+1));
    }
    m=read();
    while(m--)
    {
        int opt=read();
        if(opt==1)
        {
            int x=read()+1;
            T.split(x,n+1);
            write(T.size[n+1]-1),puts("");
        }
        else
        {
            int x=read()+1,y=read();
            T.cut(x,x+val[x]<=n?(x+val[x]):(n+1));
            val[x]=y;
            T.link(x,x+val[x]<=n?(x+val[x]):(n+1));
        }
    }
    return 0;
}
posted @ 2018-12-31 18:05  JSOI爆零珂学家yzhang  阅读(228)  评论(0编辑  收藏  举报