Codeforces13 E. Holes(分块)

题意:

给定长度为n的序列a,a(i)表示将石子丢到i,会从i位置会跳到i+a(i),一直重复直到跳出n
m次操作,操作有两种:
1.将a[x]修改为y
2.询问将式子丢到x,最后一步从哪个位置跳出n,以及总共跳了多少步

数据范围:n,m<=1e5

解法:

分块

对于每个块,预处理:
cnt[i]表示从i跳出当前块需要的次数
nt[i]表示从i跳出当前块之后到达的位置
last[i]变送从i跳出当前块最后一步的位置

对于修改操作,重新处理a[x]所在块,复杂度O(sq)
对于查询操作,是按块跳的,最多跳sq次,复杂度O(sq)

总复杂度O(m*sq)

总结:
当块与块之间相互不影响时,就可以用分块做

code:

#include<bits/stdc++.h>
using namespace std;
const int maxm=1e5+5;
int cnt[maxm];//cnt[i]表示从i跳出当前块需要的次数
int nt[maxm];//nt[i]表示从i跳出当前块之后到达的位置
int last[maxm];//last[i]变送从i跳出当前块最后一步的位置
//
int belong[maxm];
int l[maxm],r[maxm];
int block;
int num;
//
int a[maxm];
int n,m;
//
void build(){
    block=sqrt(n);
    num=n/block+(n%block!=0);
    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--){
        if(i+a[i]>r[belong[i]]){
            cnt[i]=1;
            nt[i]=min(i+a[i],n+1);
            last[i]=i;
        }else{
            cnt[i]=cnt[i+a[i]]+1;
            nt[i]=nt[i+a[i]];
            last[i]=last[i+a[i]];
        }
    }
}
void update(int x,int y){//重新构造这个块
    a[x]=y;
    for(int i=r[belong[x]];i>=l[belong[x]];i--){
        if(i+a[i]>r[belong[i]]){
            cnt[i]=1;
            nt[i]=min(i+a[i],n+1);
            last[i]=i;
        }else{
            cnt[i]=cnt[i+a[i]]+1;
            nt[i]=nt[i+a[i]];
            last[i]=last[i+a[i]];
        }
    }
}
void ask(int x){
    int out=x,num=0;
    int now=x;
    while(now!=n+1){
        out=last[now];
        num+=cnt[now];
        now=nt[now];
    }
    printf("%d %d\n",out,num);
}
signed main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++){
        scanf("%d",&a[i]);
    }
    build();
    while(m--){
        int op;scanf("%d",&op);
        if(op==0){//a[x]=y
            int x,y;scanf("%d%d",&x,&y);
            update(x,y);
        }else{
            int x;scanf("%d",&x);
            ask(x);
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_44178736/article/details/107858672