• [HNOI2010]弹飞绵羊(分块)


    题目描述

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

    题解

      这里需要我们处理出每一块中,进入某个点后,会进入下一个块的哪一个点,需要几次才能弹出块,修改时记得同时修改相应块的内容。

      靠大佬自己思维了。

    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<iostream>
    using namespace std;
    const int N=500001;
    int n,m,ch[N],tmp,belong[N],l[N],r[N],num,out[N],sum[N];
    int read()
    {
        int x=0,w=1;char ch=getchar();
        while(ch>'9'||ch<'0'){if(ch=='-')w=-1;ch=getchar();}
        while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
        return w*x;
    }
    
    void build()
    {
        num=tmp;if(tmp*tmp<n)num++;
    
        for(int i=1;i<=num;i++)
        {
            l[i]=num*(i-1)+1;r[i]=num*i;
            
        }
        r[num]=n;
    
        int s=1 ;
        for (int i=1;i<=n;i++) {if (i>r[s]) s++; belong[i]=s;}
    }
    
    void change(int left,int right)
    {
        for(int i=right;i>=left;i--)
        {
            if(i+ch[i]>r[belong[i]])sum[i]=1,out[i]=i+ch[i];
            else sum[i]=sum[i+ch[i]]+1,out[i]=out[i+ch[i]];
        }
    }
    
    int main()
    {
        n=read();tmp=sqrt(n);
        for(int i=1;i<=n;i++)
        {
            ch[i]=read();
        }
        build();
        change(1,n);
        m=read();
        for(int i=1;i<=m;i++)
        {
            int qwq;
            qwq=read();
            if(qwq==1)
            {
                int x;x=read();x++;
                int ans=sum[x],qwq=out[x];
                for(int i=belong[x];i<=tmp&&qwq<=n;i++)
                ans+=sum[qwq],qwq=out[qwq];
                printf("%d
    ",ans);
            }
            else 
            {
                int x,y;x=read();x++;y=read();ch[x]=y;
                change(l[belong[x]],r[belong[x]]);
            }
        }
        return 0;
    }
  • 相关阅读:
    vue项目刷新当前页面最优解决方式
    nprogress 进度条
    Element Tabs 标签页实现右键自定义菜单
    vue项目中清除定时器(清除定时器不成功)
    Vue.Draggable学习总结 ( Draggable为基于Sortable.js的vue组件,用以实现拖拽功能 )
    vue缓存及路由和生命周期触发的完整流程
    Vue webpack 打包Vue项目后动态配置API接口地址及配置文件
    Vue——element-ui下拉框的几个参数
    Vue——radio、checkbox、select 标签的双向绑定
    Vue——路由的跳转方式
  • 原文地址:https://www.cnblogs.com/hhh1109/p/8597759.html
Copyright © 2020-2023  润新知