BZOJ 2002 [Hnoi2010]Bounce 弹飞绵羊:分块

Posted Leohh

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ 2002 [Hnoi2010]Bounce 弹飞绵羊:分块相关的知识,希望对你有一定的参考价值。

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2002

题意:

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

  n<=200000,m<=100000

 

题解:

  分块。

  对于每个元素,维护两个值:

    nex[i]:表示从当前点第一次跳到下一个块的点的位置。

    stp[i]:表示跳出块要用的步数。

  update在一个块内暴力从后往前维护。

  query不断地跳区间就行了。

  两个操作都是单次O(sqrt(N))。

 

AC Code:

 1 #include <iostream>
 2 #include <stdio.h>
 3 #include <string.h>
 4 #include <math.h>
 5 #define MAX_N 200005
 6 
 7 using namespace std;
 8 
 9 int n,m;
10 int len,cnt;
11 int k[MAX_N];
12 int pos[MAX_N];
13 int nex[MAX_N];
14 int stp[MAX_N];
15 
16 void read()
17 {
18     scanf("%d",&n);
19     for(int i=1;i<=n;i++)
20     {
21         scanf("%d",&k[i]);
22     }
23 }
24 
25 void init_block()
26 {
27     len=sqrt(n)+1;
28     cnt=ceil((double)n/(double)len);
29     for(int i=1;i<=n;i++)
30     {
31         pos[i]=(i-1)/len+1;
32     }
33     for(int i=n;i>0;i--)
34     {
35         if(i+k[i]>n) nex[i]=0,stp[i]=1;
36         else if(i+k[i]>pos[i]*len) nex[i]=i+k[i],stp[i]=1;
37         else nex[i]=nex[i+k[i]],stp[i]=stp[i+k[i]]+1;
38     }
39 }
40 
41 void update(int x,int y)
42 {
43     k[x]=y;
44     for(int i=min(pos[x]*len,n);i>(pos[x]-1)*len;i--)
45     {
46         if(i+k[i]>n) nex[i]=0,stp[i]=1;
47         else if(i+k[i]>pos[i]*len) nex[i]=i+k[i],stp[i]=1;
48         else nex[i]=nex[i+k[i]],stp[i]=stp[i+k[i]]+1;
49     }
50 }
51 
52 int query(int x)
53 {
54     int sum=0;
55     while(x)
56     {
57         sum+=stp[x];
58         x=nex[x];
59     }
60     return sum;
61 }
62 
63 void work()
64 {
65     init_block();
66     scanf("%d",&m);
67     int opt,x,y;
68     while(m--)
69     {
70         scanf("%d%d",&opt,&x);
71         if(opt==1) printf("%d\n",query(x+1));
72         else
73         {
74             scanf("%d",&y);
75             update(x+1,y);
76         }
77     }
78 }
79 
80 int main()
81 {
82     read();
83     work();
84 }

 

以上是关于BZOJ 2002 [Hnoi2010]Bounce 弹飞绵羊:分块的主要内容,如果未能解决你的问题,请参考以下文章

bzoj2002HNOI2010Bounce 弹飞绵羊

bzoj 2002: [Hnoi2010]Bounce 弹飞绵羊

BZOJ2002: [Hnoi2010]Bounce 弹飞绵羊

BZOJ2002:[HNOI2010]弹飞绵羊——题解

[BZOJ 2002][Luogu 3203][HNOI2010]Bounce 弹飞绵羊

[bzoj2002][Hnoi2010]Bounce弹飞绵羊_LCT