BZOJ-2002(分块)

Description
某天,Lostmonkey发明了一种超级弹力装置,为了在他的绵羊朋友面前显摆,他邀请小绵羊一起玩个游戏。游戏一开始,Lostmonkey在地上沿着一条直线摆上n个装置,每个装置设定初始弹力系数ki,当绵羊达到第i个装置时,它会往后弹ki步,达到第i+ki个装置,若不存在第i+ki个装置,则绵羊被弹飞。绵羊想知道当它从第i个装置起步时,被弹几次后会被弹飞。为了使得游戏更有趣,Lostmonkey可以修改某个弹力装置的弹力系数,任何时候弹力系数均为正整数。

Input
第一行包含一个整数n,表示地上有n个装置,装置的编号从0到n-1,接下来一行有n个正整数,依次为那n个装置的初始弹力系数。第三行有一个正整数m,接下来m行每行至少有两个数i、j,若i=1,你要输出从j出发被弹几次后被弹飞,若i=2则还会再输入一个正整数k,表示第j个弹力装置的系数被修改成k。对于20%的数据n,m<=10000,对于100%的数据n<=200000,m<=100000

Output
对于每个i=1的情况,你都要输出一个需要的步数,占一行。

Sample Input

4                              
1 2 1 1
3
1 1
2 1 1
1 1

Sample Output

2
3

解题思路:我们分块,然后对于每一个块中的点,记录它到它能到达的在自身这个块中的最前面的点, 然后记录这个步数,那么在之后更新时,我们就只需要更新一个块的所有点就可以了,然后在查询答案时,将所有的块中可以走到的第一个点的步数加上就可以了。
代码:

#pragma GCC optimize(2)
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <string>
#include <vector>
#include <set>
#include <map>
#include <bitset>
#include <queue>
#include <random>
#include <time.h>
using namespace std;
#define int long long
#define ls root<<1
#define rs root<<1|1
const int maxn = 2e5 + 7;
const int inf = 0x3f3f3f3f;
std::mt19937 rnd(233);
int belong[maxn], posl[maxn], posr[maxn], len;
int st[maxn], posnext[maxn], a[maxn];
inline int ask(int x)
{
    int ans = 0;
    while(x){
        ans += st[x];
        x = posnext[x];
    }
    return ans;
}
signed main()
{
#ifndef ONLINE_JUDGE
    //freopen("in.in", "r", stdin);
    //freopen("out.out", "w", stdout);
#endif
    int n;
    scanf("%lld", &n);
    len =(int) sqrt(n);
    for (int i = 1;i<=n;i++){
        scanf("%lld", a + i);
        belong[i] = (i - 1) / len + 1;
    }
    int cnt = n / len + (n % len ? 1 : 0);
    for (int i = 1; i <= cnt;i++){
        posl[i] = (i - 1) * len + 1;
        posr[i] = i * len;
    }
    posr[cnt] = n;
    for (int i = n; i > 0;i--){
        if(i+a[i]>n)
            st[i] = 1;
        else{
            if(belong[i]==belong[i+a[i]]){
                st[i] = st[i+a[i]]+1;
                posnext[i] = posnext[i + a[i]];
            }
            else{
                st[i] = 1;
                posnext[i] = i + a[i];
            }
        }
    }
    int m;
    scanf("%lld", &m);
    while(m--){
        int op, x, y;
        scanf("%lld%lld", &op, &x);
        x++;
        if(op==1){
            printf("%lld\n", ask(x));
        }
        else{
            scanf("%lld", &y);
            a[x] = y;
            for (int i = x; i >= posl[belong[x]];i--){
                if(i+a[i]>n)
                    st[i] = 1, posnext[i] = 0;
                else{
                    if(belong[i]==belong[i+a[i]]){
                        posnext[i] = posnext[i + a[i]];
                        st[i] = st[i + a[i]] + 1;
                    }
                    else{
                        posnext[i] = i + a[i];
                        st[i] = 1;
                    }
                }
            }
        }
    }
}
发布了43 篇原创文章 · 获赞 9 · 访问量 2432
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 大白 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览