bzoj 2002 分块

bzoj 2002 分块

题目链接

传送门
cin关同步会被卡了,step数组表示当前块跳到下一个块的步数,to数组表示当前块跳到下一块的会到那个位置(下标从0开始)

#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int N = 2e5+10;
int a[N],to[N],step[N];
int n,block,m;
int query(int x)
{
    int ans = 0;
    for(int i=x;i!=-1;i=to[i])
    {
        ans += step[i];
    }
    return ans;
}
void update(int x,int k)
{
    int start = ((x-1)/block)*block + 1;
    int end = ((x-1)/block + 1)*block;
    a[x] = k;
    for(int i=end;i>=start;i--)
    {
        if(i+a[i]>n)
        {
            to[i] = -1;
            step[i] = 1;
        }
        else if(i+a[i]>end)
        {
            to[i] = i+a[i];
            step[i] = 1;
        }
        else
        {
            to[i] = to[i+a[i]];
            step[i] = step[i+a[i]] + 1;
        }
    }
}
int main()
{
    scanf("%d",&n);
    block = sqrt(n);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
    }
    for(int i=n;i>=1;i--)
    {
        int t = ((i-1)/block + 1)*block;
        if(i+a[i]>n)
        {
            to[i] = -1;
            step[i] = 1;
        }
        else if(i+a[i]>t)
        {
            to[i] = i+a[i];
            step[i] = 1;
        }
        else
        {
            to[i] = to[i+a[i]];
            step[i] = step[i+a[i]] + 1;
        }
    }
    scanf("%d",&m);
    for(int i=1;i<=m;i++)
    {
        int opt,l,x,k;
        scanf("%d%d",&opt,&x);
        if(opt==1)
            cout << query(x+1) << "
";
        else
        {
            scanf("%d",&k);
            update(x+1,k);
        }
    }
    return 0;
}
原文地址:https://www.cnblogs.com/hh13579/p/12421353.html