Codeforces Problem - 13E Holes

Holes


        n个洞1~n,每个洞有一个power,a1~an。把球扔到第i个洞,它会蹦到第i+ai个洞去(一直往后蹦,直到n以外)。有m次操作,分为两种,0是询问把求扔到某个洞,最后能到达哪个洞以及会蹦多少次,1是修改某个洞的power。

        这是在CF上一篇讲数据结构的博客上看到的题,学到了一个新的姿势。。方法是分块维护,每块的大小是sqrt(n)。对每个洞,维护它能在本块内蹦多少次和最后到达块内哪个洞。这样,每次操作不管是查询还是修改,它的复杂度都是sqrt(n),卡着时限过了这道题。。


#include <iostream>
#include <stdio.h>
#include <string>
#include <map>
#include <vector>
#include <stack>
#include <queue>
#include <string.h>
#include <algorithm>
#include <math.h>

using namespace std;

const int maxn=100010;

int power[maxn];

int last_hole[maxn];
int num[maxn];
int group[maxn];

int n,m;
void fun(int pos){
	if(group[pos]!=group[pos+power[pos]]){
		num[pos]=1;
		last_hole[pos]=pos;
		return;
	}
	num[pos]=num[pos+power[pos]]+1;
	last_hole[pos]=last_hole[pos+power[pos]];
}

int main(){
	
	cin>>n>>m;
	for(int i=1;i<=n;i++){
		scanf("%d",&power[i]);
	}
	
	int SQRT=sqrt(n);
	int cnt=-1;
	group[0]=1;
	for(int i=1;i<=n;i++){
		cnt++;
		if(cnt==SQRT){
			group[i]=group[i-1]+1;
			cnt=0;
		}else{
			group[i]=group[i-1];
		}
	}
	group[0]=0;
	
	//计算本组最后一个洞 
	//计算到下组要跳几次
	for(int i=n;i>=1;i--){
		fun(i);
	}
	
	for(int i=1;i<=m;i++){
		int op,a,b;
		scanf("%d",&op);
		if(op){
			scanf("%d",&a);
			int last=a;
			int cnt=0;
			while(1){
				cnt+=num[last];
				last=last_hole[last];
				if(last+power[last]>n)break;
				last+=power[last];
			}
			printf("%d %d\n",last,cnt);
		}else{
			scanf("%d%d",&a,&b);
			power[a]=b;
			while(1){
				fun(a);
				a--;
				if(group[a]!=group[a+1])break;
			}
		}
	}
	return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值