码迷,mamicode.com
首页 > 其他好文 > 详细

[bzoj] 2002 弹飞绵羊 || LCT

时间:2018-02-25 13:14:09      阅读:153      评论:0      收藏:0      [点我收藏+]

标签:char   log   push   swa   splay   problem   link   update   div   

原题

简单的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\n",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;
}

[bzoj] 2002 弹飞绵羊 || LCT

标签:char   log   push   swa   splay   problem   link   update   div   

原文地址:https://www.cnblogs.com/mrha/p/8468773.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!