• Bounce 弹飞绵羊 HYSBZ


    题意:

    题目描述

    分析:

      分块就是暴力,但用了一个块来有优化时间,要想用分块,就要想办法借助块来优化。一开始做这道题目,完全想不出来要维护什么东西,分块怎么用。看了别人的思路后,明白了要维护每个点跳出其所在块的跳的次数和跳到的点。写了之后,一交就 (WA) 了。后来发现是修改点的时候,没有把其所在块中该点前面的点也修改。因为,修改该点时,它们各自维护的东西可能会受到影响。然后,又交,(T) 了。发现,是在修改各个点时,完全可以用递推的方式来改,而我每次都重新开始。

    代码:

    #include <bits/stdc++.h>
    using namespace std;
    const int N=2e5+5;
    struct node
    {
        int step,pos;
    }point[N];
    int k[N],belong[N],L[N],R[N];
    int num,block,n;
    void read(int &x)
    {
        x=0;
        int f=1;
        char ch=getchar();
        while(!isdigit(ch))
        {
            if(ch=='-')
                f=1;
            ch=getchar();
        }
        while(isdigit(ch))
        {
            x=(x<<3)+(x<<1)+ch-'0';
            ch=getchar();
        }
        x*=f;
    }
    void build()
    {
        block=sqrt(n);
        num=n/block;
        if(n%block)
            num++;
        for(int i=1;i<=num;i++)
        {
            L[i]=(i-1)*block+1;
            R[i]=i*block;
        }
        R[num]=n;
        for(int i=1;i<=n;i++)
            belong[i]=(i-1)/block+1;
        for(int i=n;i>=1;i--)
        {
            if(i+k[i]>R[belong[i]])
            {
                point[i].step=1;
                point[i].pos=i+k[i];
            }
            else
            {
                point[i].step=point[i+k[i]].step+1;
                point[i].pos=point[i+k[i]].pos;
            }
        }
    }
    void update(int p)
    {
        for(int i=p;i>=L[belong[p]];i--)
        {
            if(i+k[i]>R[belong[p]])
            {
                point[i].step=1;
                point[i].pos=i+k[i];
            }
            else
            {
                point[i].step=point[i+k[i]].step+1;
                point[i].pos=point[i+k[i]].pos;
            }
        }
    }
    int query(int p)
    {
        int ans=0;
        while(p<=n)
        {
            ans+=point[p].step;
            p=point[p].pos;
        }
        return ans;
    }
    int main()
    {
        int m,op,a,b;
        read(n);
        for(int i=1;i<=n;i++)
            read(k[i]);
        build();
        read(m);
        while(m--)
        {
            read(op),read(a);
            if(op==1)
                printf("%d
    ",query(a+1));
            else if(op==2)
            {
                read(k[a+1]);
                update(a+1);
            }
        }
        return 0;
    }
    
    
  • 相关阅读:
    AtCoder Grand Contest 001F Wide Swap
    生成函数/母函数入门学习
    树的点分治入门小结
    树链剖分入门小结
    有重复元素的全排列
    二项式界
    二项系数
    排列问题、组合问题
    容斥原理
    P3372 【模板】线段树 1
  • 原文地址:https://www.cnblogs.com/1024-xzx/p/12532846.html
Copyright © 2020-2023  润新知