bzoj 2002

2002: [Hnoi2010]Bounce 弹飞绵羊

Time Limit: 10 Sec  Memory Limit: 259 MB
Submit: 3848  Solved: 2051
[Submit][Status]

Description

某天,Lostmonkey发明了一种超级弹力装置,为了在他的绵羊朋友面前显摆,他邀请小绵羊一起玩个游戏。游戏一开始,Lostmonkey在地上沿着一条直线摆上n个装置,每个装置设定初始弹力系数ki,当绵羊达到第i个装置时,它会往后弹ki步,达到第i+ki个装置,若不存在第i+ki个装置,则绵羊被弹飞。绵羊想知道当它从第i个装置起步时,被弹几次后会被弹飞。为了使得游戏更有趣,Lostmonkey可以修改某个弹力装置的弹力系数,任何时候弹力系数均为正整数。

Input

第一行包含一个整数n,表示地上有n个装置,装置的编号从0到n-1,接下来一行有n个正整数,依次为那n个装置的初始弹力系数。第三行有一个正整数m,接下来m行每行至少有两个数i、j,若i=1,你要输出从j出发被弹几次后被弹飞,若i=2则还会再输入一个正整数k,表示第j个弹力装置的系数被修改成k。对于20%的数据n,m<=10000,对于100%的数据n<=200000,m<=100000

Output

对于每个i=1的情况,你都要输出一个需要的步数,占一行。

Sample Input


1 2 1 1 
3
1 1
2 1 1
1 1

Sample Output

2
3
 
 
我的第一题LCT。现在仍理解得不是很透彻。
 
LCT:通过access操作把一棵树分解成若干条路径,用splay维护路径的信息,使复杂度达到logN级别
 
这题只有两个操作:
1.询问某节点的深点
2.修改某个节点的父亲
 
只用了access操作.
 
继续努力吧。LCT还要多写几题啊.

 

#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<cstring>

using namespace std;

//fa[i],i如果不是splay的根,则表示i在splay中的父节点,否则表示i所splay表示的链连接的树中的父节点
//root[i],表示i是否是splay的根

struct tree{
    int ls,rs;
}tr[200011];

int fa[200011],size[200011];
bool root[200011];
int i,n,x,z,kind,m;

void update(int x)
{
    size[x]=size[tr[x].ls]+size[tr[x].rs]+1;
}

void right_rotate(int x)
{
    int y,z;
    y=tr[x].ls;
    z=tr[y].rs;
    tr[x].ls=z;
    tr[y].rs=x;
    fa[z]=x;
    if(tr[fa[x]].ls==x)tr[fa[x]].ls=y;
    if(tr[fa[x]].rs==x)tr[fa[x]].rs=y;
    fa[y]=fa[x];
    fa[x]=y;
    if(root[x]==true){
        root[y]=true;
        root[x]=false;
    }
    update(x);
    update(y);
}

void left_rotate(int x)
{
    int y,z;
    y=tr[x].rs;
    z=tr[y].ls;
    tr[x].rs=z;
    tr[y].ls=x;
    fa[z]=x;
    if(tr[fa[x]].ls==x)tr[fa[x]].ls=y;
    if(tr[fa[x]].rs==x)tr[fa[x]].rs=y;
    fa[y]=fa[x];
    fa[x]=y;
    if(root[x]==true){
        root[y]=true;
        root[x]=false;
    }
    update(x);
    update(y);
    
}

void splay(int x)
{
    while(root[x]==false){
        if(tr[fa[x]].rs==x)left_rotate(fa[x]);
        else right_rotate(fa[x]);
    }
}

void access(int x)
{
    int z;
    splay(x);
    while(fa[x]!=0){
        z=fa[x];
        splay(z);
        root[tr[z].rs]=true;
        root[x]=false;
        tr[z].rs=x;
        update(z);
        x=z;
        splay(x);
    }
}

int main()
{
    memset(root,true,sizeof(root));
    scanf("%d",&n);
    for(i=1;i<=n;i++){
        scanf("%d",&x);
        fa[i]=i+x;
        if(fa[i]>n)fa[i]=n+1;
    }
    for(i=1;i<=n+1;i++)size[i]=1;
    scanf("%d",&m);
    for(i=1;i<=m;i++){
        scanf("%d",&kind);
        if(kind==1){
            scanf("%d",&x);
            x++;
            access(x);
            splay(x);
            printf("%d\n",size[tr[x].ls]);
        }
        else{
            scanf("%d%d",&x,&z);
            x++;
            access(x);
            splay(x);
            fa[tr[x].ls]=fa[x];
            root[tr[x].ls]=true;
            tr[x].ls=0;
            size[x]=size[tr[x].rs]+1;
            fa[x]=x+z;
            if(fa[x]>n)fa[x]=n+1;
        }
    }
}

 

posted on 2014-08-10 21:35  razorjxt  阅读(112)  评论(0编辑  收藏