Holes(河鼠入洞)

Posted yufenglin

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Holes(河鼠入洞)相关的知识,希望对你有一定的参考价值。

好的,我们先来看题:

有N个洞,每个洞有相应的弹力,能把这个球弹到i+power[i] 位置。当球的位置>N时即视为被弹出

输入: 第一行两个正整数N,M,下面N个数代表初始的power[i] 之后M行分别代表M个操作 共有两种操作: 0 a b 把a位置的弹力改成b 1 a 在a处放一个球,输出球被弹出前共被弹了多少次,最后一次落在哪个洞。

输出:对于每个操作2,输出两个题目中要求的值(空格隔开)

1<=N<=100000 1<=M<=100000

输入样例#1: 复制
8 5
1 1 1 1 1 2 8 2
1 1
0 1 3
1 1
0 3 4
1 2
输出样例#1: 复制
8 7
8 5
7 3

其实这道题和弹飞绵羊区别并不大,同样也是利用分块来解决,只不过还要求离开前的最后位置。我们还是简单的理顺一下这道题的思路吧:

思路其实很简单,我们将整个序列分成若干个块(块的大小取决于数据,但是我们一般都会默认为√n),对于每一块的每一个点我们只要维护他弹出这个块还需几步和弹出之后会到达哪一个点即可。

关于修改,由于每一个块之间都是相互独立的,所以单点修改只需要维护每一个块就可以了,并且由于每一个点的数据都建立在他后面块的基础上,所以我们对于每一个块都需要倒着来进行维护。

而对于查询次数我们只要循着每一个点的指向,累加每一个点的sum值,大于n的时候跳出即可

可是如果要查询位置呢?

这里就隐藏着一个巨大的坑点:由于每一个点记录的只是弹出这个方块所到达的位置,所以求得的最终位置并不是实际的位置,还要再往后找一遍(就在一个块内,时间复杂度可以忽略)就完事了!

最后,附上本题代码:

 1 #include<cstdio>
 2 #include<cmath>
 3 #include<algorithm>
 4 using namespace std;
 5 struct pot
 6 {
 7     int to,k,conti,sum;
 8 }p[100005];
 9 int size,cnt=1,n,ac,ans;
10 void change(int ct)
11 {
12     //printf("%d
",size);
13     for(int j=min(ct*size,n);j>(ct-1)*size;j--)
14     {
15         if(j + p[j].k > ct * size || j + p[j].k > n) p[j].sum = 1,p[j].to = j + p[j].k;
16         else
17         {
18             p[j].to=p[j+p[j].k].to;
19             p[j].sum=p[j+p[j].k].sum + 1;
20         }
21         //printf("%d
",p[j].to);
22     }
23 }
24 void query(int y)
25 {
26     ans=0;
27     while(y<=n)
28     {
29         ans+=p[y].sum;
30         //printf("%d
",ans);
31         if(p[y].to>n) ac=y;
32         y=p[y].to;
33     }
34     while(ac+p[ac].k<=n)
35     {
36         ac+=p[ac].k;
37     }
38 }
39 int main()
40 {
41     int temp = 0,m;
42     scanf("%d%d",&n,&m);
43     size=sqrt(n);
44     for(int i=1;i<=n;i++)
45     {
46         temp++;
47         if(temp>size)
48         {
49             cnt++;
50             temp=1;
51         }
52         scanf("%d",&p[i].k);
53         p[i].conti=cnt;
54     }
55     //if(temp != 0) cnt++;
56     //printf("%d
",cnt);
57     for(int i=cnt;i >= 1;i--)
58         change(i);
59     for(int i=1;i<=m;i++)
60     {
61         int x,y,z;
62         scanf("%d%d",&x,&y);
63         if(x==0)
64         {
65             scanf("%d",&z);
66             p[y].k=z;
67             //printf("%d
",p[y].k); 
68             change(p[y].conti);
69         } 
70         else
71         {
72             query(y);
73             printf("%d %d
",ac,ans);
74         }
75     }
76     return 0;
77 }

 

以上是关于Holes(河鼠入洞)的主要内容,如果未能解决你的问题,请参考以下文章

UVA 356 - Square Pegs And Round Holes

E - Holes

OpenCV中的Matlab'bridge''shrink'和'holes'等效形态学运算

Finding Black Holes 1

Finding Black Holes 2

《柳林风声》阅读笔记