• Evanyou Blog 彩带


      题目传送门

    弹飞绵羊

    题目描述

    某天,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。

     

    输出格式:

     

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

     

    输入输出样例

    输入样例#1: 
    4
    1 2 1 1
    3
    1 1
    2 1 1
    1 1
    输出样例#1: 
    2
    3

    说明

    对于20%的数据n,m<=10000,对于100%的数据n<=200000,m<=100000


      分析:

      把每个装置看作一个点,然后连边,每次修改弹力值就可以看作断边和连边,可以用LCT维护。那么查询显然就直接求该点原树到根节点的距离。维护的时候比较方便,很多函数都可以省略。

      Code:

    //It is made by HolseLee on 30th June 2018
    //Luogu.org P3203
    #include<bits/stdc++.h>
    using namespace std;
    const int N=2e5+7;
    int n,m,a[N],fa[N],s[N],ch[N][2];
    inline int read()
    {
        char ch=getchar();int num=0;bool flag=false;
        while(ch<'0'||ch>'9'){if(ch=='-')flag=true;ch=getchar();}
        while(ch>='0'&&ch<='9'){num=num*10+ch-'0';ch=getchar();}
        return flag?-num:num;
    }
    inline void pushup(int x)
    {
        s[x]=s[ch[x][0]]+s[ch[x][1]]+1;
    }
    inline bool isroot(int x)
    {
        return (ch[fa[x]][0]!=x)&&(ch[fa[x]][1]!=x);
    }
    inline void rotate(int x)
    {
        int y=fa[x],z=fa[y];    
        int k=(ch[y][1]==x);
        int w=ch[x][k^1];
        if(!isroot(y))ch[z][ch[z][1]==y]=x;
        ch[x][k^1]=y;ch[y][k]=w;
        if(w)fa[w]=y;fa[y]=x;fa[x]=z;
        pushup(y);
    }
    inline void splay(int x)
    {
        while(!isroot(x)){
            int y=fa[x],z=fa[y];
            if(!isroot(y))
            ((ch[y][0]==x)^(ch[z][0]==y))?
            rotate(y):rotate(x);
            rotate(x);}
        pushup(x);
    }
    inline void access(int x)
    {
        for(int y=0;x;x=fa[y=x])
        splay(x),ch[x][1]=y,pushup(x);
    }
    int main()
    {
        n=read();int x,y,z;
        for(int i=1;i<=n;i++){
            s[i]=1;x=read();
            if(i+x<=n)fa[i]=i+x;}
        m=read();
        for(int i=1;i<=m;i++){
            x=read();y=read();
            if(x==1){
                ++y;
                access(y);splay(y);
                printf("%d
    ",s[y]);
            }
            else{
                z=read();++y;
                access(y);splay(y);
                ch[y][0]=fa[ch[y][0]]=0;
                if(y+z<=n)fa[y]=y+z;
                pushup(y);}
        }
        return 0;
    }
  • 相关阅读:
    [Baltic2013]ballmachine BZOJ3133
    [Jxoi2012]奇怪的道路 BZOJ3195 状压DP
    [Baltic 2011]Lamp BZOJ2346
    可并堆
    [Jsoi2016]最佳团体 BZOJ4753 01分数规划+树形背包/dfs序
    点分治
    J2EE WEB应用架构分析
    {经典}springmvc+mybatis+restful+webservice Jeesz分布式架构
    深入Spring Boot:那些注入不了的 Spring 占位符 ( ${} 表达式 )
    G1 垃圾收集器之对象分配过程
  • 原文地址:https://www.cnblogs.com/cytus/p/9247679.html
Copyright © 2020-2023  润新知