HYSBZ 2002 分块

Posted キリト

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HYSBZ 2002 分块相关的知识,希望对你有一定的参考价值。

 

 

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2002

题意:中文题面

思路:考虑分块,每个位置维护一个跳出该块需要的步数cnt[],和跳出该块后到达下一块的哪个位置to[]。

关于修改操作:直接修改所在块的左端点到修改的位置。 然后需要逆序修改。因为后面的位置的值会影响到前面位置的值。

关于询问操作:直接暴力计算即可。

#define _CRT_SECURE_NO_DEPRECATE
#include<stdio.h>  
#include<string.h>  
#include<cstring>
#include<algorithm>  
#include<queue>  
#include<math.h>  
#include<time.h>
#include<vector>
#include<iostream>
#include<map>
using namespace std;
typedef long long int LL;
const int MAXN = 200000 + 10;
int belong[MAXN], block, num, L[MAXN], R[MAXN];
int n, q;
int a[MAXN], cnt[MAXN], to[MAXN];
void build(){
    block = (int)sqrt(n + 0.5);
    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 = num; i>0; i--){
        for (int j = R[i]; j >= L[i]; j--){
            if (j + a[j]>R[i]){
                cnt[j] = 1; to[j] = min(n+1,j + a[j]);
            }
            else{
                cnt[j] = cnt[j + a[j]] + 1; to[j] = min(n+1,to[j + a[j]]);
            }
        }
    }
}
void modify(int pos, int val){
    a[pos] = val;
    for (int i = pos; i >= L[belong[pos]]; i--){
        if (i + a[i]>R[belong[pos]]){
            cnt[i] = 1;  to[i] = min(i + a[i], n + 1);
        }
        else{
            cnt[i] = cnt[i + a[i]] + 1; to[i] = min(to[i + a[i]], n + 1);
        }
    }
}
int query(int pos){
    int ans = 0;
    for (int i = pos; i <= n; i = to[i]){
        ans += cnt[i];
    }
    return ans;
}
int main(){
    //#ifdef kirito
    //    freopen("in.txt", "r", stdin);
    //    freopen("out.txt", "w", stdout);
    //#endif
    //    int start = clock();
    while (~scanf("%d", &n)){
        for (int i = 1; i <= n; i++){ scanf("%d", &a[i]); }
        build(); scanf("%d", &q);
        int type, pos, v;
        for (int i = 1; i <= q; i++){
            scanf("%d", &type);
            if (type == 1){
                scanf("%d", &pos); pos++; printf("%d\n", query(pos));
            }
            else{
                scanf("%d%d", &pos, &v); pos++; modify(pos, v);
            }
        }
    }
    //#ifdef LOCAL_TIME
    //    cout << "[Finished in " << clock() - start << " ms]" << endl;
    //#endif
    return 0;
}

 

以上是关于HYSBZ 2002 分块的主要内容,如果未能解决你的问题,请参考以下文章

HYSBZ - 2957 分块

(分块)楼房重建 HYSBZ - 2957

「日常训练与知识学习」树的分块(王室联邦,HYSBZ-1086)

bzoj2002 弹飞绵羊 分块

bzoj2002弹飞绵羊——分块

BZOJ 2002 [Hnoi2010]Bounce 弹飞绵羊(分块)