zoukankan      html  css  js  c++  java
  • 【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. }  
  • 相关阅读:
    【深入学习MySQL】MySQL的索引结构为什么使用B+树?
    【Python爬虫】爬了七天七夜,终于爬出了博客园粉丝数排行榜!
    【BAT面试题系列】面试官:你了解乐观锁和悲观锁吗?
    深入学习MySQL事务:ACID特性的实现原理
    深入学习Redis(5):集群
    深入学习Redis(4):哨兵
    谈谈微信支付曝出的漏洞
    深入学习Redis(3):主从复制
    深入学习Redis(2):持久化
    Spring中获取request的几种方法,及其线程安全性分析
  • 原文地址:https://www.cnblogs.com/NSD-email0820/p/9850833.html
Copyright © 2011-2022 走看看