洛谷 P3203 [HNOI2010]弹飞绵羊 分块

 

我们只需将序列分成 n\sqrt{n}n 块,对于每一个点维护一个 val[i]val[i]val[i]to[i]to[i]to[i],分别代表该点跳到下一个块所需要的代价以及会跳到的节点编号。在查询时,我们最多会跳 n\sqrt{n}n 块,修改的时候将节点所在区间暴力修改即可。
Code:

#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
const int maxn = 2000000 + 3;
int arr[maxn], n, block, to[maxn], val[maxn], m, belong[maxn];
struct Data_Structure{
    inline void init(){
        block = sqrt(n);
        for(int i = n;i >= 1; --i) 
        {
            belong[i] = (i - 1) / block + 1;
            to[i] = belong[i + arr[i]] == belong[i] ? to[i + arr[i]] : i + arr[i];
            val[i] = belong[i + arr[i]] == belong[i] ? val[i + arr[i]] + 1 : 1;
        }
    }
    inline int solve(){
        int pos, ans = 0;
        scanf("%d",&pos);
        ++pos;
        while(pos <= n){
            ans += val[pos];
            pos = to[pos];
        }
        return ans;
    }
    inline void update(){
        int pos, data;
        scanf("%d%d",&pos,&data);
        ++pos;
        arr[pos] = data;
        for(int i = min(belong[pos] * block, n); i >= (belong[pos] - 1) * block + 1; --i)
        {
            to[i] = belong[i + arr[i]] == belong[i] ? to[i + arr[i]] : i + arr[i];
            val[i] = belong[i + arr[i]] == belong[i] ? val[i + arr[i]] + 1 : 1;
        }
    }
}T;
int main(){
    scanf("%d",&n);
    for(int i = 1;i <= n; ++i) scanf("%d",&arr[i]);
    T.init();
    scanf("%d",&m);
    while(m--)
    {
        int opt;
        scanf("%d",&opt);
        switch(opt)
        {
            case 1:
            {
                printf("%d\n", T.solve());
                break;
            }
            case 2:
            {
                T.update();
                break;
            }
        }
    }
    return 0;
}

  

posted @ 2018-10-16 20:08  EM-LGH  阅读(163)  评论(0编辑  收藏  举报