• P3203 [HNOI2010]弹飞绵羊


    传送门

    LCT裸题,设 $k[i]$ 为位置 $i$ 弹簧的弹力系数,那么从 $i$ 往 $i+k[i]$ 连一条边,显然所有边构成了一个森林

    直接 LCT 维护森林,询问 $x$ 就把 $x$ 到根的路径连起来 ($access(x)$) ,然后输出 $x$ 的 $splay$ 的节点数就好了

    修改也不用那么麻烦,我们 $sccess(x),splay(x)$ 后 $c[x][0]$ 的子树就是所有 $x$ 的祖先节点,直接断开就好了

    注意不要 $query(read(),read())$,$read()$在函数里是反着读入的!

    代码比 $LCT$ 模板还简单

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #include<cstring>
    #include<vector>
    using namespace std;
    typedef long long ll;
    inline int read()
    {
        int x=0,f=1; char ch=getchar();
        while(ch<'0'||ch>'9') { if(ch=='-') f=-1; ch=getchar(); }
        while(ch>='0'&&ch<='9') { x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); }
        return x*f;
    }
    const int N=4e5+7;
    int n,m;
    int c[N][2],fa[N],sz[N];
    inline void pushup(int x) { sz[x]=sz[c[x][0]]+sz[c[x][1]]+1; }
    inline bool notroot(int x) { return (c[fa[x]][0]==x)|(c[fa[x]][1]==x); }
    inline void rotate(int x)
    {
        int y=fa[x],z=fa[y],d=(c[y][1]==x);
        if(notroot(y)) c[z][c[z][1]==y]=x;
        fa[x]=z; fa[y]=x; fa[c[x][d^1]]=y;
        c[y][d]=c[x][d^1]; c[x][d^1]=y;
        pushup(y); pushup(x);
    }
    inline void splay(int x)
    {
        while(notroot(x))
        {
            int y=fa[x],z=fa[y];
            if(notroot(y))
            {
                if(c[y][0]==x ^ c[z][0]==y) rotate(x);
                else rotate(y);
            }
            rotate(x);
        }
    }
    inline void access(int x)
    {
        for(int y=0;x;y=x,x=fa[x])
            splay(x),c[x][1]=y,pushup(x);
    }
    inline int query(int x) { access(x);splay(x); return sz[x]; }
    inline void change(int x,int y)
    {
        access(x); splay(x);
        c[x][0]=fa[c[x][0]]=0;
        if(x+y<=n) fa[x]=x+y;
        pushup(x);
    }
    int main()
    {
        //freopen("data.in","r",stdin);
        //freopen("data.out","w",stdout);
        int a; n=read();
        for(int i=1;i<=n;i++)//编号从1开始 
        {
            sz[i]=1,a=read();
            if(i+a<=n) fa[i]=i+a;//连边 
        }
        m=read();
        int b,c;
        while(m--)
        {
            a=read();
            if(a==1) printf("%d
    ",query(read()+1));//题目编号从0开始,所以要+1 
            else
            {
                b=read(); c=read();
                change(b+1,c);
            }
        }
        return 0;
    }
  • 相关阅读:
    Java实现 蓝桥杯VIP 算法训练 装箱问题
    Java实现 蓝桥杯VIP 算法训练 入学考试
    Qt4.6.2已编译二进制版本在VS2005中的问题
    函数可重入问题reentrant functions(函数执行过程中可以被中断,允许多个副本)
    QT的Paint 系统
    取clientdataset detal中的 更新数据, 将detal 转 数据库脚本sql
    delphi 八字排盘源码(post数据以后,又分析数据)
    Working with Entity Relations in OData
    图片轮播插件Nivo Slider
    跨域访问 REST API
  • 原文地址:https://www.cnblogs.com/LLTYYC/p/10576742.html
Copyright © 2020-2023  润新知