LCT(Bounce 弹飞绵羊,BZOJ 2002)

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2002


参考博客:

http://blog.csdn.net/wzq_qwq/article/details/47397539

http://blog.csdn.net/saramanda/article/details/55210418

http://blog.csdn.net/clove_unique/article/details/50991685


pushup函数用于更新Auxiliary Tree中子树的节点个数。

凡是Auxiliary Tree会变化的地方(树形态的变化和树重构的变化)都要更新一下,不过追根溯源,只要在rotate函数,access函数以及update函数中使用这个pushup函数即可。


代码

/**************************************************************
    Problem: 2002
    User: 2015190026
    Language: C++
    Result: Accepted
    Time:2508 ms
    Memory:11064 kb
****************************************************************/
 
#include<stdio.h>
#include<algorithm>
using namespace std;
const int maxn = 200010;
 
struct node
{
    int fa,ch[2];
    bool reverse,is_root;
    int s;
    void init()
    {
        fa=ch[0]=ch[1]=0;
        reverse=0;
        is_root=1;
        s=1;
    }
}T[maxn];
 
void pushup(int x)
{
    T[x].s=T[T[x].ch[0]].s+T[T[x].ch[1]].s+1;
}
 
int getson(int x)
{
    return x==T[T[x].fa].ch[1];
}
 
void pushreverse(int x)
{
    if(!x) return;
    swap(T[x].ch[0],T[x].ch[1]);
    T[x].reverse^=1;
}
 
void pushdown(int x)
{
    if(T[x].reverse)
    {
        pushreverse(T[x].ch[0]);
        pushreverse(T[x].ch[1]);
        T[x].reverse=false;
    }
}
 
void rotate(int x)
{
    if(T[x].is_root) return;
    int k=getson(x);
    int fa=T[x].fa;
    int fafa=T[fa].fa;
    pushdown(fa);
    pushdown(x);
    T[fa].ch[k]=T[x].ch[k^1];
    if(T[x].ch[k^1]) T[T[x].ch[k^1]].fa=fa;
    T[x].ch[k^1]=fa;
    T[fa].fa=x;
    T[x].fa=fafa;
    if(T[fa].is_root)
    {
        T[fa].is_root=false;
        T[x].is_root=true;
    }
    else
    {
        T[fafa].ch[fa==T[fafa].ch[1]]=x;
    }
    pushup(fa);
    pushup(x);
}
 
void push(int x)
{
    if(!T[x].is_root) push(T[x].fa);
    pushdown(x);
}
 
void Splay(int x)
{
    push(x);
    for(int fa;!T[x].is_root;rotate(x))
    {
        if(!T[fa=T[x].fa].is_root)
        {
            rotate((getson(x)==getson(fa))?fa:x);
        }
    }
}
 
void access(int x)
{
    int y=0;
    do
    {
        Splay(x);
        T[T[x].ch[1]].is_root=true;
        T[T[x].ch[1]=y].is_root=false;
        pushup(x);
        x=T[y=x].fa;
    }while(x);
}
 
void mroot(int x)
{
    access(x);
    Splay(x);
    pushreverse(x);
}
 
void link(int u,int v)
{
    mroot(u);
    T[u].fa=v;
}
 
void cut(int u,int v)
{
    mroot(u);
    access(v);
    Splay(v);
    pushdown(v);
    T[T[v].ch[0]].fa=T[v].fa;
    T[T[v].ch[0]].is_root=true;
    T[v].fa=0;T[v].ch[0]=0;
    pushup(v);
}
 
int n,Q;
int k[maxn];
 
void debug()
{
    puts("------------");
    for(int i=1;i<=n+1;i++)
    {
        printf("%d:",i);
        printf("fa:%d l:%d r:%d ir:%d rev:%d s:%d\n",T[i].fa,T[i].ch[0],T[i].ch[1],T[i].is_root,T[i].reverse,T[i].s);
    }
    puts("------------");
}
 
int qry(int x)
{
    //debug();
    mroot(n+1);
    //debug();
    access(x);
    //debug();
    Splay(x);
    //debug();
    return T[T[x].ch[0]].s;
}
 
void handle(int x,int y)
{
    cut(x,min(x+k[x],n+1));
    //debug();
    k[x]=y;
    link(x,min(x+k[x],n+1));
    //debug();
}
 
void solve()
{
    T[0].init();
    T[0].s=0;
    for(int i=1;i<=n;i++)
    {
        scanf("%d",k+i);
        T[i].init();
    }
    T[n+1].init();
    for(int i=1;i<=n;i++)
        link(i,min(i+k[i],n+1));
    int a,b,c;
    scanf("%d",&Q);
    while(Q--)
    {
        scanf("%d %d",&a,&b);
        if(a==1) printf("%d\n",qry(b+1));
        else
        {
            scanf("%d",&c);
            handle(b+1,c);
        }
    }
}
 
int main()
{
    while(~scanf("%d",&n)) solve();
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值