• [bzoj] 2002 弹飞绵羊 || LCT


    原题

    简单的LCT练习题。
    我们发现对于一个位置x,他只能跳到位置x+k,也就是唯一的父亲去。加入我们将弹飞的绵羊定义为跳到了n+1,那么这就形成了一棵树。而因为要修改k,所以这颗树是动态连边的,那么LCT就可以解决了。
    至于询问,我们把n+1变成根,然后access(x)将x到n+1的路径变为实路径,splay(x),因为每次是向父亲弹,所以sze[ls[x]]即为答案。
    //想知道为什么不是sze[x]-1

    AC代码:

    #include<cstdio>
    #include<algorithm>
    #define N 200010
    #define which(u) (ls[fa[(u)]]==(u))
    #define isroot(u) (!fa[(u)] || (ls[fa[(u)]]!=(u) && rs[fa[u]]!=(u)))
    using namespace std;
    int n,m,fa[N],ls[N],rs[N],a[N],sze[N];
    bool rev[N];
    char s[20];
    
    void update(int x)
    {
        sze[x]=1;
        if (ls[x]) sze[x]+=sze[ls[x]];
        if (rs[x]) sze[x]+=sze[rs[x]];
    }
    
    void rotate(int u)
    {
        int v=fa[u],w=fa[v],b=which(u)?rs[u]:ls[u];
        if (!isroot(v)) (which(v)?ls[w]:rs[w])=u;
        which(u)?(ls[v]=b,rs[u]=v):(rs[v]=b,ls[u]=v);
        fa[u]=w,fa[v]=u;
        if (b) fa[b]=v;
        if (v) update(v);
        if (u) update(u);
    }
    
    void pushdown(int u)
    {
        if (!rev[u]) return ;
        rev[ls[u]]^=1;
        rev[rs[u]]^=1;
        swap(ls[u],rs[u]);
        rev[u]=0;
    }
    
    void splay(int u)
    {
        static int stk[N],top;
        stk[top=1]=u;
        while (!isroot(stk[top])) stk[top+1]=fa[stk[top]],top++;
        while (top) pushdown(stk[top--]);
        while (!isroot(u))
        {
    	if (!isroot(fa[u]))
    	{
    	    if (which(u)==which(fa[u])) rotate(fa[u]);
    	    else rotate(u);
    	}
    	rotate(u);
        }
    }
    
    void access(int u)
    {
        int v=0;
        while (u)
        {
    	splay(u);
    	rs[u]=v;
    	v=u;
    	u=fa[u];
        }
    }
    
    void makeroot(int u)
    {
        access(u);
        splay(u);
        rev[u]^=1;
    }
    
    void link(int u,int v)
    {
        makeroot(v);
        fa[v]=u;
    }
    
    void cut(int u,int v)
    {
        makeroot(u);
        access(v);
        splay(v);
        ls[v]=fa[u]=0;
    }
    
    int query(int x)
    {
        makeroot(n+1);
        access(x);
        splay(x);
        return sze[ls[x]];
    }
    
    int main()
    {
        scanf("%d",&n);
        for (int i=1,x;i<=n;i++)
        {
    	scanf("%d",&x);
    	a[i]=(i+x<=n)?i+x:n+1;
    	fa[i]=a[i];
    	sze[i]=1;
        }
        sze[n+1]=1;
        scanf("%d",&m);
        while (m--)
        {
    	int op,x,y;
    	scanf("%d%d",&op,&x);
    	++x;
    	if (op==1)
    	    printf("%d
    ",query(x));
    	else
    	{
    	    scanf("%d",&y);
    	    cut(x,a[x]);
    	    a[x]=(x+y<=n)?x+y:n+1;
    	    link(x,a[x]);
    	}
        }
        return 0;
    }
    
  • 相关阅读:
    Ubuntu 12.04 + nginx + php5 + phpfpm安装,并进行多站点配置
    PHP的FTP类
    php操作mongodb 分组排序
    mongodb 条件操作符
    PHP匿名登录FTP
    PHP连接到FTP服务器注意事项
    Java SE第二讲 原生数据类型Primitive Data Type
    java se 第五讲 运算符续
    Java SE 第一讲 入门jdk的下载安装
    Java SE第三讲:原生数据类型的使用陷阱
  • 原文地址:https://www.cnblogs.com/mrha/p/8468773.html
Copyright © 2020-2023  润新知