• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
hyxzc
博客园    首页    新随笔    联系   管理    订阅  订阅

c++之路进阶——codevs2333(弹飞绵羊)

2333 弹飞绵羊

 

2010年省队选拔赛湖南

 时间限制: 1 s
 空间限制: 128000 KB
 题目等级 : 大师 Master
 
 
 
题目描述 Description

Lostmonkey发明了一种超级反弹装置。为了在绵羊朋友面前显摆,他邀请小绵羊一起玩个游戏。游戏一开始,Lostmonkey在地上沿一条直线摆放 n个反弹装置,并按从前往后的方式将反弹装置依次编号为 0 到 n-1,对 0≤i≤n-1,为第 i 个反弹装置设定了初始弹力系数 ki,当绵羊落到第 i 个反弹装置上时,它将被往后弹出 ki 步,即落到第 i+ki 个反弹装置上,若不存在第i+ki个反弹装置,则绵羊被弹飞。绵羊想知道: 从第i个反弹装置开始, 它被弹出几次 (含被弹飞的那次)后会被弹飞。为使游戏更有趣,Lostmonkey 还可以修改某个反弹装置的弹力系数,但任何时候弹力系数均为正整数。

输入描述 Input Description

输入文件第一行是一个整数n,表示地上摆放n个反弹装置,输入文件第二行是用空格隔开的n个正整数k0,k1,…,kn-1,分别表示n个反弹装置的初始弹力系数。输入文件第三行是一个正整数m,表示后面还有m行输入数据。接下来的m行,每行至少有用空格隔开的两个整数i和j,若i=1,则你要输出从第j个反弹装置开始,被弹出几次后会被弹飞;若i=2,则该行有用空格隔开的三个整数i,j和k,表示第j个反弹装置的弹力系数被修改为k。

输出描述 Output Description

包含的行数等于输入文件最后m行中i=1的行数。第h行输出一个整数,表示对输入中给出的第h个求弹出次数的问题,基于n个反弹装置当时的弹力系数,求出的弹出次数。

样例输入 Sample Input

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

样例输出 Sample Output

2 
3

数据范围及提示 Data Size & Hint

输入的数据保证20%的数据满足n,m≤10000。100%的数据满足n≤200000,m≤100000

题解

    块状链表,

    维护跳出该块的步数(bushu),所到达的点(finish),对同一块中进行压缩路径(虽然有点不像,但我是这样理解的)。

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cmath>
 4 #define maxn 200010
 5 
 6 using namespace std;
 7 
 8 int sqrp,n,m,a[maxn],l[1005],r[1005],bushu[maxn],finish[maxn],belong[maxn],gs;
 9 
10 int find(int x)
11   {
12       int ans=0;
13       for(;;)
14         {
15             ans+=bushu[x];
16             if (!finish[x]) return ans;
17             x=finish[x];
18         }
19   }
20 
21 int main()
22   {
23       scanf("%d",&n);
24     for (int i=1;i<=n;i++)
25         scanf("%d",&a[i]);
26     sqrp=sqrt(n);
27     if (n%sqrp)     gs=n/sqrp+1;
28             else gs=n/sqrp;
29     for (int i=1;i<=gs;i++)
30         l[i]=(i-1)*sqrp+1,r[i]=i*sqrp;                 
31       r[gs]=n;
32       for (int i=1;i<=n;i++)
33          belong[i]=(i-1)/sqrp+1;
34       for (int i=n;i>0;i--)
35         {
36             if(i+a[i]>n)bushu[i]=1;
37         else if(belong[i]==belong[i+a[i]])
38         bushu[i]=bushu[i+a[i]]+1,finish[i]=finish[i+a[i]];
39         else bushu[i]=1,finish[i]=i+a[i];
40         }
41       scanf("%d",&m);
42       for (int i=1;i<=m;i++)
43          {
44               int aa,bb,cc;
45               scanf("%d",&aa);
46               if (aa==1)
47                  scanf("%d",&bb),printf("%d\n",find(bb+1));
48                  else
49                   {
50                         scanf("%d%d",&bb,&cc);
51                         a[bb+1]=cc;
52                         for(int i=bb+1;i>=l[belong[bb+1]];i--)
53                       if(belong[i]==belong[i+a[i]])
54                   bushu[i]=bushu[i+a[i]]+1,finish[i]=finish[i+a[i]];
55                   else bushu[i]=1,finish[i]=i+a[i];
56                   }
57          }
58       return 0;
59     }  

 

posted @ 2016-01-14 20:39  hyxzc  阅读(399)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3