P3203 [HNOI2010]弹飞绵羊(LCT)

LCT真是好用的数据结构啊(瘫)

思路

首先在每个弹力装置和它能到达的弹力装置处连边
会发现长的像一颗树一样
然后涉及到了修改,就是动态的连边和删除边,可以想到用LCT维护
然后对于修改,cut掉原来的边,再link新的节点即可
查询把(j,x+10)split出来,然后x+10节点中存放的就是需要的信息,去掉本身的sz就是1之后就是答案

代码

#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
struct SPT{
    int son[2],sz,tag;
}SPT[200100];
int fa[200100],n,a[200100],m;
void pushup(int o){
    SPT[o].sz=SPT[SPT[o].son[0]].sz+SPT[SPT[o].son[1]].sz+1;    
}
void pushdown(int o){
    if(o&&SPT[o].tag){
        SPT[SPT[o].son[0]].tag^=1;
        SPT[SPT[o].son[1]].tag^=1;
        swap(SPT[o].son[0],SPT[o].son[1]);
        SPT[o].tag=0;
    }
}
bool isrl(int o){
    return o==SPT[fa[o]].son[1];
}
bool isroot(int o){
    return (SPT[fa[o]].son[0]!=o)&&(SPT[fa[o]].son[1]!=o);
}
void rorate(int o){
    if(isroot(o))
        return;
    int f=fa[o];
    int g=fa[f];
    int which=isrl(o);
    pushdown(f);
    pushdown(o);
    //o--g
    fa[o]=g;
    if(!isroot(f))
        SPT[g].son[SPT[g].son[1]==f]=o;
    //
    fa[SPT[o].son[which^1]]=f;
    SPT[f].son[which]=SPT[o].son[which^1];
    SPT[o].son[which^1]=f;
    fa[f]=o;
    pushup(f);
    pushup(o);
}
void push(int o){
    if(!isroot(o))
        push(fa[o]);
    pushdown(o);
}
void splay(int o){
    push(o);
    for(int f;!isroot(o);rorate(o)){
        if(!isroot(f=fa[o]))        
            rorate((isrl(f)==isrl(o))?f:o);
    }
}
void access(int o){
    for(int y=0;o;o=fa[y=o])
        splay(o),SPT[o].son[1]=y,pushup(o);
}
void makeroot(int o){
    access(o);
    splay(o);
    SPT[o].tag^=1;
    pushdown(o);
}
int findroot(int o){
    access(o);
    splay(o);
    pushdown(o);
    while(SPT[o].son[0])
        pushdown(o=SPT[o].son[0]);
    return o;
}
void split(int x,int y){
    makeroot(x);
    access(y);
    splay(y);
}
void link(int x,int y){
    makeroot(x);
    if(findroot(y)!=x)
        fa[x]=y;
}
void cut(int x,int y){
    makeroot(x);
    if(findroot(y)==x&&fa[x]==y&&SPT[y].son[0]==x&&SPT[x].son[1]==0)
        fa[x]=0,SPT[y].son[0]=0,pushup(y);
}
int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        scanf("%d",&a[i]);
        SPT[i].sz=1;
    }
    SPT[n+10].sz=1;
    for(int i=1;i<=n;i++)
        link(i,(i+a[i]>n)?n+10:i+a[i]);
    scanf("%d",&m);
    for(int i=1;i<=m;i++){
        int opt,j,k;
        scanf("%d %d",&opt,&j);
        j++;
        if(opt==1){
            split(j,n+10);
            printf("%d\n",SPT[n+10].sz-1);
        }
        else{
            scanf("%d",&k);
            cut(j,(j+a[j]>n)?n+10:j+a[j]);
            a[j]=k;
            link(j,(j+a[j]>n)?n+10:j+a[j]);
        }
    }
}
posted @ 2018-12-03 12:41  dreagonm  阅读(117)  评论(0编辑  收藏  举报