cf E. Holes

E. Holes

题意:每一个洞都有一个能量值>>>一个球可以从这个位置跳到i+a[i]的位置>>>

考虑维护球能跳到下一个的位置>>倒着维护>>则能够>>找出球的最终位置 nxt[x]

然后考虑更改的操作>>每次更改这个位置的球,我们必须更改>>他之前的所有位置

复杂度肯定要爆的>>>

考虑优化>>>我能不能将更改和查询全部转换为sqrt 或者log 级别的东西>>考虑分块>>

在分块操作中我们让每一个球每次跳过1块的距离>>

在更新的操作中需要更新一个块>>>>>>>>>

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int a[N],nxt[N],bel[N],L[N],R[N],blo,n,m,cnt;
int num[N],last[N];
void build(){
    cnt=n/blo;if(n%blo) cnt++;
    for(int i=1;i<=n;i++) bel[i]=(i-1)/blo+1;
    for(int i=1;i<=cnt;i++) L[i]=(i-1)*blo+1,R[i]=min(n,i*blo);
}
void update(int x,int y){
    if(y>n){
        num[x]=1;
        last[x]=x;
        nxt[x]=n+1;
    }
    else if(bel[x]==bel[y]){
        last[x]=last[y];
        nxt[x]=nxt[y];
        num[x]=num[y]+1;
    }
    else {
        nxt[x]=y;
        last[x]=x;
        num[x]=1;
    }
}
void query(int x){
    int res=num[x];int end_=last[x];
    while(1){
        x=nxt[x];
        if(x>n) break;
        end_=last[x];
        res+=num[x];
    }
    printf("%d %d\n",end_,res);
}
int main(){
    scanf("%d%d",&n,&m);blo=sqrt(n);
    build();
    for(int i=1;i<=n;i++){
        scanf("%d",&a[i]);
        if(i+a[i]>n) a[i]=n+1-i;
    }
    for(int i=n;i>=1;i--) update(i,i+a[i]);
    int cas,x,y;
    while(m--){
        scanf("%d",&cas);
        if(cas){
            scanf("%d",&x);
            query(x);
        }
        else{
            scanf("%d%d",&x,&y);
            a[x]=y;
            int tmp=bel[x];
            for(int i=x;i>=L[tmp];i--){
                update(i,i+a[i]);
            }
        }
    }
    return 0;
}

  

 

转载于:https://www.cnblogs.com/vainglory/p/9177974.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值