zoukankan      html  css  js  c++  java
  • 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 }
  • 相关阅读:
    [转载]PhotoShop性能优化
    SVN常用命令
    [转载]SVN使用教程
    MyEclipse Java Build Path详解
    MyEclipse安装后需要进行的配置
    c#中base64加密解密
    C# MD5 加密
    C# http Post 方法
    EPF与Myeclipse 增强代码自动智能提示
    汉字代码手册
  • 原文地址:https://www.cnblogs.com/yufenglin/p/10392359.html
Copyright © 2011-2022 走看看