zoukankan      html  css  js  c++  java
  • 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
    ",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]);
            }
        }
    }
    
  • 相关阅读:
    如何使用分布式锁
    深入理解 ValueTask
    Tuple VS ValueTuple
    RxJS——调度器(Scheduler)
    RxJS——主题(Subject)
    RxJS——Operators
    RxJS——订阅(Subscription)
    RxJS——可观察的对象(Observable)
    Ext.Net 使用总结之GridPanel的删除事件
    使用 NuGet 管理项目库
  • 原文地址:https://www.cnblogs.com/dreagonm/p/10057810.html
Copyright © 2011-2022 走看看