bzoj 2202 [HNOI2010] Bounce 弹飞绵羊(分块)

链接:https://www.lydsy.com/JudgeOnline/problem.php?id=2002

思路:和之前那道树分块的题很像,只不过那道是在树上,这道简单些在序列上

还是维护两个数组:

num[] 跳出当前块需要的次数

nex[] 跳出当前块到达的点的下标

实现代码:

#include<bits/stdc++.h>
using namespace std;
const int M = 2e5+10;
int n,m,block,cnt,l[M],r[M],a[M],blo[M],nex[M],num[M],op;
int query(int x){
    int sum = 0;
    while(x){
        sum += num[x];
        x = nex[x];
    }
    return sum;
}

int main()
{
    int x,y;
    scanf("%d",&n);
    block = sqrt(n);
    for(int i = 1;i <= n;i ++){
        scanf("%d",&a[i]);
    }
    for(int i = 1;i <= n;i ++) blo[i] = (i-1)/block+1;
    for(int i = 1;i <= blo[n];i++) l[i] = (i-1)*block+1;
    for(int i = n;i > 0;i --){
        if(i + a[i] > n) num[i] = 1;
        else if(blo[i] == blo[i+a[i]])
            num[i] = num[i+a[i]]+1,nex[i] = nex[i+a[i]];
        else
            num[i] = 1,nex[i] = i+a[i];
    }
    scanf("%d",&m);
    for(int i = 1;i <= m;i ++){
        scanf("%d%d",&op,&x);
        x++;
        if(op == 1) printf("%d
",query(x));
        else{
            scanf("%d",&y);
            a[x] = y;
            for(int i = x;i >= l[blo[x]];i --){
                if(blo[i] == blo[i+a[i]])
                    num[i] = num[i+a[i]]+1,nex[i] = nex[i+a[i]];
                else num[i] = 1,nex[i] = i+a[i];
            }
        }
    }
    return 0;
}
原文地址:https://www.cnblogs.com/kls123/p/9556851.html