Luogu 3203 BZOJ 2002——弹飞绵羊

Luogu 3203  BZOJ 2002——弹飞绵羊

题意概括

给定一个序列,有N个装置,绵羊在不同

其实就是个裸LCT。

从i能跳到i+k即可以理解为i到i+k之间有一条连边

修改操作即断边然后连边。

在查询时只需要把要出发的点成为原树的根,然后访问n+1,把n+1splay到根,然后结果就在n+1的子树中了。

#include<cstdio>
#include<algorithm>
#define maxn 200100
using namespace std;
struct TREE{
    int c[2],sum,fa,rev;
}tree[maxn];
int stack[maxn],n,a[maxn];
int read(){
    int w=0;char c=getchar();
    while(c<'0'||c>'9') c=getchar();
    while(c>='0'&&c<='9') w=w*10+c-48,c=getchar();
    return w;
}
inline void update(int x){
    tree[x].sum=tree[tree[x].c[0]].sum+tree[tree[x].c[1]].sum+1;
}
inline void pushdown(int x){
    if(!tree[x].rev) return;
    int l=tree[x].c[0],r=tree[x].c[1];
    if(l) tree[l].rev^=1;
    if(r) tree[r].rev^=1;
    swap(tree[x].c[0],tree[x].c[1]);
    tree[x].rev^=1;
}
bool isroot(int x){
    return tree[tree[x].fa].c[0]!=x&&tree[tree[x].fa].c[1]!=x;
}
bool get(int x) {
return x==tree[tree[x].fa].c[1];}
void rotate(int x){
    int f=tree[x].fa,ff=tree[tree[x].fa].fa,opt=get(x);
    tree[f].c[opt]=tree[x].c[opt^1];
    tree[tree[x].c[opt^1]].fa=f; 
    if(!isroot(f)) tree[ff].c[get(f)]=x;
    tree[x].fa=ff;tree[f].fa=x;
    tree[x].c[opt^1]=f;
    update(f);update(x);
}
void splay(int x){
    int top=0,tmp=x;stack[++top]=x;
    while(!isroot(tmp))stack[++top]=tree[tmp].fa,tmp=tree[tmp].fa;
    while(top)pushdown(stack[top]),top--;
    while(!isroot(x)){
        rotate(x); 
    }
} 
void access(int x){
    int son=0;
    while(x){
        splay(x);tree[x].c[1]=son;
        update(x);son=x;x=tree[x].fa;
    }
}
void makeroot(int x){
    access(x);splay(x);tree[x].rev^=1;
}
void link(int x,int y){
    makeroot(x);tree[x].fa=y;
    splay(x);
}
void cut(int x,int y){
    makeroot(x);access(y);
    splay(y);tree[y].c[0]=tree[x].fa=0;
}
int query(int x,int y){
    makeroot(x);access(y);splay(y);
    return tree[y].sum;
}
int getfa(int x){
    access(x);splay(x);
    while(tree[x].c[0]){
        pushdown(x);x=tree[x].c[0];
        splay(x);
    } 
    return x;
}
void change(int x,int y){
    makeroot(x);
//    tree[x].val=y;
    update(x);
}
void answer(int i){
    makeroot(i); access(n+1); splay(n+1);
//    printf("1");
    printf("%d
",tree[n+1].sum-1);
}
int main(){
    int x,i,opt,m,k;
    n=read();
    for(i=1;i<=n;i++){
        x=a[i]=read();
        if(i+x<=n) link(i,i+x);
        else link(i,n+1);
    }
    m=read();
    for(i=1;i<=m;i++){
        opt=read();x=read()+1; 
        if(opt==1) answer(x);
        else {k=read();if(a[x]+x<=n)cut(x,a[x]+x);else cut(x,n+1);
        if(x+k<=n)link(x,x+k);else link(x,n+1);a[x]=k;}
    }
}
弹飞绵羊
原文地址:https://www.cnblogs.com/Fish-/p/8270617.html