bzoj2002 弹飞绵羊

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的情况,你都要输出一个需要的步数,占一行。

用块状树维护由跳跃一次后位置到跳跃前位置连边构成的有根树。

每操作O(n0.5)次重构整棵树

均摊时间复杂度O(n1.5)

#include<cstdio>
#include<cmath>
int n,m,rt;
int cs,cb,tt=0,cb2;
int fa[200005],fw[200005],v[200005],dep[200005],top[200005];
int enx[800005],epv[800005],ew[800005],ep;
inline int min(int a,int b){
    return a<b?a:b;
}
void addedge(int a,int b){
    fa[b]=a;
    ew[ep]=b;
    enx[epv[ep]=epv[a]]=ep;
    enx[ep]=a;
    fw[b]=epv[a]=ep++;
}
void deledge(int a){
    int x=fw[a],pv=epv[x];
    epv[enx[pv]=enx[x]]=pv;
}
int getdep(int x){
    int ans=-1;
    while(x){
        ans+=dep[x];
        x=fa[top[x]];
    }
    return ans;
}
void build(int w){
    ++cs;
    if(cs<=cb)top[w]=top[fa[w]],dep[w]=dep[fa[w]]+1;
    else cs=0,top[w]=w,dep[w]=1;
    for(int i=enx[w],u=ew[i];u=ew[i];i=enx[i])build(u);
}
int tp,tpn,dp;
void dfs(int w){
    if(top[w]!=tp)return;
    top[w]=tpn;
    dep[w]=dp;
    ++dp;
    for(int i=enx[w],u=ew[i];u=ew[i];i=enx[i])dfs(u);
    --dp;
}
int main(){
    scanf("%d",&n);
    cb=sqrt(n);
    cb2=cb*3;
    rt=n+1;
    for(int i=1;i<=n;i++)scanf("%d",v+i);
    for(int i=1;i<=rt;i++)enx[i]=epv[i]=i;ep=rt+1;
    for(int i=1;i<=n;i++)addedge(min(i+v[i],rt),i);
    scanf("%d",&m);
    cs=cb,build(rt);
    while(m--){
        int op,a,b;
        scanf("%d",&op);
        if(op==2){
            scanf("%d%d",&a,&b);++a;
            v[a]=b;
            deledge(a);
            addedge(min(a+v[a],rt),a);
            tp=top[a],tpn=a,dp=1,dfs(a);
            if(++tt>cb2)cs=cb,build(rt),tt=0;
        }else{
            int vans;
            scanf("%d",&a);++a;
            printf("%d
",vans=getdep(a));
        }
    }
    return 0;
}
原文地址:https://www.cnblogs.com/ccz181078/p/5289664.html