BZOJ2002 HNOI2010 弹飞绵羊Bounce

Description

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

Input

第一行包含一个整数n,表示地上有n个装置,装置的编号从0到n-1,接下来一行有n个正整数,依次为那n个装置的初始弹力系数。第三行有一个正整数m,接下来m行每行至少有两个数i、j,若i=1,你要输出从j出发被弹几次后被弹飞,若i=2则还会再输入一个正整数k,表示第j个弹力装置的系数被修改成k。对于20%的数据n,m<=10000,对于100%的数据n<=200000,m<=100000

Output

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

Sample Input

4

1 2 1 1

3

1 1

2 1 1

1 1

Sample Output

2

3

 


 

最喜欢的题目......

不会LCT,分块做的;

对于每一个装置,维护几个值:跳出所在块所需步数及相应的落点;

预处理:从后向前维护;

查询:模拟一边就行;

修改:从修改位置向前直到所在块的左端点全都暴力改一遍;

代码:

 

 1 //弹飞绵羊Bounce__HNOI 2010
 2 #include<iostream>
 3 #include<cstdio>
 4 #include<cmath>
 5 using namespace std;
 6 
 7 inline void Read(int&);
 8 const int maxn = 2e5 + 5;
 9 int n, m, q;
10 int arr[maxn];
11 int blo[maxn], step[maxn], fall[maxn];
12 inline int Bounce(int);
13 
14 int main()
15 {
16     Read(n);
17     m=sqrt(n);
18     for (int i = 1; i <= n; i++)
19     {
20         Read(arr[i]);
21         blo[i] = (i - 1) / m + 1;
22     }
23     for (int i = n; i > 0; i--)//预处理
24     {
25         if (i + arr[i] > n)
26             step[i] = 1;
27         else if (blo[i] == blo[i + arr[i]])
28             step[i] = step[i + arr[i]] + 1,
29                         fall[i] = fall[i + arr[i]];
30         else
31             step[i] = 1, fall[i] = i + arr[i];
32     }
33     Read(q);
34     while(q--)
35     {
36         int ord, pos, v;
37         Read(ord), Read(pos);
38         pos++;
39         if (ord == 1)
40             printf("%d\n", Bounce(pos));//查询
41         else
42         {
43             Read(v);
44             arr[pos] = v;
45             int end = (blo[pos] - 1)*m + 1;
46             for (int i = pos; i >= end; i--)//修改
47             {
48                 if (blo[i] == blo[i + arr[i]])
49                     step[i] = step[i + arr[i]] + 1,
50                                         fall[i] = fall[i + arr[i]];
51                 else step[i] = 1, fall[i] = i + arr[i];
52             }
53         }
54     }
55     return 0;
56 }
57 
58 inline int Bounce(int pos)//查询的函数
59 {
60     int ans=0;
61     while (pos)
62     {
63         ans += step[pos];
64         pos = fall[pos];
65     }
66     return ans;
67 }
68 
69 inline void Read(int &x)
70 {
71     x=0;
72     bool f=0;
73     char c=getchar();
74     while (c<'0' || c>'9')
75     {
76         f = (c == '-');
77         c = getchar();
78     }
79     while (c >= '0'&&c <= '9')
80     {
81         x = x * 10 + c - '0';
82         c = getchar();
83     }
84     if (f) x = -x;
85     return;
86 }
posted @ 2017-10-23 16:26  Dreif  阅读(147)  评论(0编辑  收藏  举报