HYSBZ_2002_分块

http://www.lydsy.com/JudgeOnline/problem.php?id=2002

分块基础题,初次接触,很巧妙。

OJ好像挂了,没法提交。

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;

int a[200005],cnt[200005],next[200005],l[1000],r[1000],belong[200005],n,m;

void build()
{
    int block = sqrt(n);
    int 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 = n;i >= 1;i--)
    {
        int temp = i+a[i];
        if(temp > n)
        {
            cnt[i] = 1;
            next[i] = -1;
        }
        else if(belong[i] == belong[temp])
        {
            cnt[i] = cnt[temp]+1;
            next[i] = next[temp];
        }
        else
        {
            cnt[i] = 1;
            next[i] = temp;
        }
    }
}

int getsum(int x)
{
    int ans = cnt[x];
    while(next[x] > 0)
    {
        x = next[x];
        ans += cnt[x];
    }
    return ans;
}

void update(int x,int y)
{
    a[x] = y;
    for(int i = x;i >= l[belong[x]];i--)
    {
        int temp = i+a[i];
        if(temp > n)
        {
            cnt[i] = 1;
            next[i] = -1;
        }
        else if(belong[i] == belong[temp])
        {
            cnt[i] = cnt[temp]+1;
            next[i] = next[temp];
        }
        else
        {
            cnt[i] = 1;
            next[i] = temp;
        }
    }
}
int main()
{
    scanf("%d",&n);
    for(int i = 1;i <= n;i++)   scanf("%d",&a[i]);
    build();
    scanf("%d",&m);
    while(m--)
    {
        int i,j,k;
        scanf("%d%d",&i,&j);
        if(i == 1)  printf("%d
",getsum(j+1));
        else
        {
            scanf("%d",&k);
            update(j+1,k);
        }
    }
    return 0;
}
原文地址:https://www.cnblogs.com/zhurb/p/5933091.html