• 【HNOI2010】弹飞绵羊


    题面

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

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

    分析

    经典分块。本来是有两种暴力求解的方法,

    1. 修改时O(N)求出每个点弹出去的次数,可以O(1)查询。
    2. 查询时O(N)模拟,计算弹出去的次数,可以O(1)修改。

    于是我们需要把复杂度均摊一下,就用到了分块。在每一个块内维护弹出这个块需要的次数,以及掉到哪里。

    修改的时候也只需要修改这一个块里的点弹出去的次数和弹到的位置。最后的时间复杂度就(N√N)

    代码

    1. #include<bits/stdc++.h>  
    2. using namespace std;  
    3. #define N 200020  
    4. int n,m,t,op,x,y;  
    5. int k[N],pos[N],L[N],R[N],step[N],nxt[N];  
    6. template<class T>  
    7. inline void read(T &x)  
    8. {  
    9.     x=0;static char c=getchar();   
    10.     while(c<'0'||c>'9') c=getchar();    
    11.     while(c>='0'&&c<='9')x=x*10+c-'0',c=getchar();  
    12. }  
    13.   
    14. inline int cal(int x)  
    15. {  
    16.     int tmp=0;  
    17.     while(1)  
    18.     {  
    19.         tmp+=step[x];  
    20.         if(nxt[x]==0)break;  
    21.         x=nxt[x];  
    22.     }  
    23.     return tmp;  
    24. }  
    25.   
    26. int main()  
    27. {  
    28.     read(n);t=sqrt(n);  
    29.     for(int i=1;i<=n;i++)read(k[i]);  
    30.     for(int i=1;i<=t;i++)L[i]=(i-1)*t+1,R[i]=i*t;  
    31.     if(R[t]<n)t++,L[t]=R[t-1]+1,R[t]=n;  
    32.     for(int i=1;i<=t;i++)  
    33.         for(int j=L[i];j<=R[i];j++)  
    34.             pos[j]=i;  
    35.     for(int i=n;i>=1;i--)  
    36.     {  
    37.         if(i+k[i]>n)step[i]=1;  
    38.         else if(pos[i]==pos[i+k[i]])step[i]=step[i+k[i]]+1,nxt[i]=nxt[i+k[i]];  
    39.         else step[i]=1,nxt[i]=i+k[i];  
    40.     }  
    41.     read(m);  
    42.     while(m--)  
    43.     {  
    44.         read(op);read(x);x++;  
    45.         if(op==1)printf("%d ",cal(x));  
    46.         else  
    47.         {  
    48.             read(y);k[x]=y;  
    49.             for(int i=x;i>=L[pos[x]];i--)  
    50.                 if(pos[i]==pos[i+k[i]])step[i]=step[i+k[i]]+1,nxt[i]=nxt[i+k[i]];  
    51.             else step[i]=1,nxt[i]=i+k[i];  
    52.         }  
    53.     }  
    54.     return 0;  
    55. }  
  • 相关阅读:
    DateTime类型的一个Bug
    无痛苦的软件维护——被遗忘的需求
    完全命令行.NET开发
    无痛苦的软件维护——文档和代码
    .NET初学者架构设计指南(一)Hello world的时代
    NGOSS的一点简单概念
    软件的逻辑层次
    VSTS for Testers学习笔记目录
    How Google Tests Software (出书,停止更新)
    推荐——《浪潮之巅》(据传稍后会出书,停止更新)
  • 原文地址:https://www.cnblogs.com/NSD-email0820/p/9850833.html
Copyright © 2020-2023  润新知