CodeForces-13E 分块

给一个数组,有两种操作,一种是将a位数改成b,一种是判断从a点跳几次能跳出数组,每次跳从a到x【a】+a

题解:用两个数组记录,每次点跳出下一个块 的次数,和跳到下一个块 的位置,用块来不断更新,查找的时候直接暴力跳每一个块,到最后一个块就挨个跳,

#include<bits/stdc++.h>
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define pii pair<int,int>
#define C 0.5772156649
#define pi acos(-1.0)
#define ll long long
#define mod 1000000007
#define ls l,m,rt<<1
#define rs m+1,r,rt<<1|1

using namespace std;

const double g=10.0,eps=1e-7;
const int N=200000+10,maxn=60000+10,inf=0x3f3f3f3f;

int n,m,block,num;
int l[N],r[N],belong[N];
int Next[N],cnt[N],a[N];
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=n;i>=1;i--)
    {
        int p=i,f=0;
        cnt[i]=1;
        while(belong[p+a[p]]==belong[p])
        {
            if(Next[p+a[p]])
            {
                cnt[i]=cnt[p+a[p]]+1;
                Next[i]=Next[p+a[p]];
                f=1;
                break;
            }
            cnt[i]++;
            p=p+a[p];
            if(p+a[p]>n)break;
        }
        if(!f)Next[i]=p+a[p];
    }
}
void update(int x,int y)
{
    a[x]=y;
    for(int i=r[belong[x]];i>=l[belong[x]];i--)
    {
        int p=i,f=0;
        cnt[i]=1;
        while(belong[p+a[p]]==belong[p])
        {
            if(Next[p+a[p]])
            {
                cnt[i]=cnt[p+a[p]]+1;
                Next[i]=Next[p+a[p]];
                f=1;
                break;
            }
            cnt[i]++;
            p=p+a[p];
            if(p+a[p]>n)break;
        }
        if(!f)Next[i]=p+a[p];
    }
}
void query(int x)
{
    int ans=1;
    while(x<=n)
    {
        if(Next[x]>n)
        {
            while(x+a[x]<=n)ans++,x=x+a[x];
            printf("%d ",x);
            break;
        }
        else
        {
            ans+=cnt[x];
            x=Next[x];
        }
    }
    printf("%d
",ans);
}
void debug()
{
    for(int i=1;i<=n;i++)
        printf("%d %d
",Next[i],cnt[i]);
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)scanf("%d",&a[i]);
    build();
   // debug();
    while(m--)
    {
        int x,y;
        scanf("%d",&x);
        if(x==0)
        {
            scanf("%d%d",&x,&y);
            update(x,y);
        }
        else
        {
            scanf("%d",&x);
            query(x);
        }
       // debug();
    }
    return 0;
}
/********************

********************/
View Code

复杂度O(n*sqrt(n)

原文地址:https://www.cnblogs.com/acjiumeng/p/7654528.html