zoukankan      html  css  js  c++  java
  • BZOJ2002[Hnoi2010]弹飞绵羊——LCT

    题目描述

    某天,Lostmonkey发明了一种超级弹力装置,为了在他的绵羊朋友面前显摆,他邀请小绵羊一起玩个游戏。游戏一开始,Lostmonkey在地上沿着一条直线摆上n个装置,每个装置设定初始弹力系数ki,当绵羊达到第i个装置时,它会往后弹ki步,达到第i+ki个装置,若不存在第i+ki个装置,则绵羊被弹飞。绵羊想知道当它从第i个装置起步时,被弹几次后会被弹飞。为了使得游戏更有趣,Lostmonkey可以修改某个弹力装置的弹力系数,任何时候弹力系数均为正整数。

    输入

    第一行包含一个整数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

    输出

    对于每个i=1的情况,你都要输出一个需要的步数,占一行。

    样例输入

    4
    1 2 1 1
    3
    1 1
    2 1 1
    1 1

    样例输出

    2
    3
     
    当跳过n之后就被弹飞,那么可以建一个虚点n+1,将弹飞看作弹到n+1这个节点上。
    i会被弹到i+ki号节点上,那么直接将i号节点和i+ki号节点连上就好了。
    修改直接断开原来连的边,重新连接一条边,LCT维护就好了。
    因为每个点只会连接一个比它编号大的点,所以最后形成了一棵树,每次询问直接查询j和n+1路径上的节点数-1即可。
    #include<set>
    #include<map>
    #include<cmath>
    #include<queue>
    #include<stack>
    #include<vector>
    #include<cstdio>
    #include<bitset>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    int n,m;
    int x,y;
    int opt;
    int s[200020][2];
    int f[200020];
    int r[200020];
    int st[200020];
    int size[200020];
    int dis[200020];
    int get(int rt)
    {
        return rt==s[f[rt]][1];
    }
    void pushup(int rt)
    {
        size[rt]=size[s[rt][0]]+size[s[rt][1]]+1;
    }
    void pushdown(int rt)
    {
        if(r[rt])
        {
            r[s[rt][0]]^=1;
            r[s[rt][1]]^=1;
            r[rt]^=1;
            swap(s[rt][0],s[rt][1]);
        }
    }
    int is_root(int rt)
    {
        return rt!=s[f[rt]][0]&&rt!=s[f[rt]][1];
    }
    void rotate(int rt)
    {
        int fa=f[rt];
        int anc=f[fa];
        int k=get(rt);
        if(!is_root(fa))
        {
            s[anc][get(fa)]=rt;
        }
        s[fa][k]=s[rt][k^1];
        f[s[fa][k]]=fa;
        s[rt][k^1]=fa;
        f[fa]=rt;
        f[rt]=anc;
        pushup(fa);
        pushup(rt);
    }
    void splay(int rt)
    {
        int top=0;
        st[++top]=rt;
        for(int i=rt;!is_root(i);i=f[i])
        {
            st[++top]=f[i];
        }
        for(int i=top;i>=1;i--)
        {
            pushdown(st[i]);
        }
        for(int fa;!is_root(rt);rotate(rt))
        {
            if(!is_root(fa=f[rt]))
            {
                rotate(get(fa)==get(rt)?fa:rt);
            }
        }
    }
    void access(int rt)
    {
        for(int x=0;rt;x=rt,rt=f[rt])
        {
            splay(rt);
            s[rt][1]=x;
            pushup(rt);
        }
    }
    void reverse(int rt)
    {
        access(rt);
        splay(rt);
        r[rt]^=1;
    }
    int find(int rt)
    {
        access(rt);
        splay(rt);
        while(s[rt][0])
        {
            rt=s[rt][0];
        }
        return rt;
    }
    void link(int x,int y)
    {
        reverse(x);
        f[x]=y;
    }
    void cut(int x,int y)
    {
        reverse(x);
        access(y);
        splay(y);
        s[y][0]=f[x]=0;
    }
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<=n+1;i++)
        {
            size[i]=1;
        }
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&x);
            dis[i]=x;
            if(i+x<=n)
            {
                link(i,i+x);
            }
            else
            {
                link(i,n+1);
            }
        }
        scanf("%d",&m);
        while(m--)
        {
            scanf("%d",&opt);
            if(opt==1)
            {
                scanf("%d",&x);
                x++;
                reverse(x);
                access(n+1);
                splay(n+1);
                printf("%d
    ",size[n+1]-1);
            }
            else
            {
                scanf("%d%d",&x,&y);
                x++;
                if(x+dis[x]<=n)
                {
                    cut(x,x+dis[x]);
                }
                else
                {
                    cut(x,n+1);
                }
                dis[x]=y;
                if(x+dis[x]<=n)
                {
                    link(x,x+dis[x]);
                }
                else
                {
                    link(x,n+1);
                }
            }
        }
    }
  • 相关阅读:
    [国嵌攻略][097][U-Boot新手入门]
    [国嵌攻略][070-095][Linux编程函数手册]
    自己写的切图工具(转)
    【总结整理】关于切图
    【总结整理】冯诺依曼体系结构
    【总结整理】面试需了解
    【总结整理】如何解决跨域问题
    【总结整理】WebGIS基础
    【总结整理】空间数据库基础
    【总结整理】WMS、WMTS、WFS
  • 原文地址:https://www.cnblogs.com/Khada-Jhin/p/9744804.html
Copyright © 2011-2022 走看看