zoukankan      html  css  js  c++  java
  • BZOJ 2002: [Hnoi2010]Bounce 弹飞绵羊

    2002: [Hnoi2010]Bounce 弹飞绵羊

    Description

    某天,Lostmonkey发明了一种超级弹力装置,为了在他的绵羊朋友面前显摆,他邀请小绵羊一起玩个游戏。游戏一开始,Lostmonkey在地上沿着一条直线摆上n个装置,每个装置设定初始弹力系数ki,当绵羊达到第i个装置时,它会往后弹ki步,达到第i+ki个装置,若不存在第i+ki个装置,则绵羊被弹飞。绵羊想知道当它从第i个装置起步时,被弹几次后会被弹飞。为了使得游戏更有趣,Lostmonkey可以修改某个弹力装置的弹力系数,任何时候弹力系数均为正整数。

    Input

    第一行包含一个整数n,表示地上有n个装置,装置的编号从0到n-1,接下来一行有n个正整数,依次为那n个装置的初始弹力系数。第三行有一个正整数m,接下来m行每行至少有两个数i、j,若i=1,你要输出从j出发被弹几次后被弹飞,若i=2则还会再输入一个正整数k,表示第j个弹力装置的系数被修改成k。对于20%的数据n,m<=10000,对于100%的数据n<=200000,m<=100000

    Output

    对于每个i=1的情况,你都要输出一个需要的步数,占一行。

    Sample Input

    4
    1 2 1 1
    3
    1 1
    2 1 1
    1 1

    Sample Output

    2
    3

    ——分割线——

    弹飞绵羊QAQ这道题目名字很亲和,其实好坑爹!一开始评测还以为要T、结果A了。好开心!

    好吧,言归正传,这道题目用分块的做法可以过。看Hzwer的博客貌似用动态树才是更好的做法Orz……

    分块的做法就是将n个机器分成根号n块,处理个机器走几步可以走出本块,并且到达哪一块的那一个机器。然后球答案的时候最多只要算根号n次,而每次更新机器也最多只要根号n次,这样把两个的复杂度平衡了。就可以过了。

    代码:【中途有一个变量写错了,特意写了个Arrest查了好久、QAQ】

    #include<cstdio>
    #include<cmath>
    using namespace std;
    int n;
    struct Node{
    	int num;
    	int index[450];
    	int k[450];
    	int step[450];
    	int to[450];
    	int next[450];
    };
    Node node[450];
    int m;
    int sn;
    int cnt=0;
    
    inline void calc(){
    	for (int i=1;i<=cnt;i++){
    		for (int j=node[i].num;j>=1;j--){
    			if (node[i].index[j]+node[i].k[j]>n){
    				node[i].step[j]=1;
    				node[i].next[j]=-1;
    			}else{
    				if (node[i].k[j]+j<=node[i].num){
    					node[i].to[j]=node[i].to[j+node[i].k[j]];
    					node[i].step[j]=node[i].step[j+node[i].k[j]]+1;
    					node[i].next[j]=node[i].next[j+node[i].k[j]];
    				}else{
    					int tempcnt=i+1;
    					int tempk=node[i].k[j]-(node[i].num-j);
    					while(tempk>node[tempcnt].num){
    						tempk-=node[tempcnt].num;
    						tempcnt++;
    					}
    					node[i].to[j]=tempcnt;
    					node[i].next[j]=tempk;
    					node[i].step[j]=1;
    				}
    			}
    		}
    	}
    }
    
    inline void calc(int index,int val){
    	node[(index-1)/sn+1].k[(index-1)%sn+1]=val;
    	int i=(index-1)/sn+1;
    	for (int j=(index-1)%sn+1;j>=1;j--){
    		if (node[i].index[j]+node[i].k[j]>n){
    				node[i].step[j]=1;
    				node[i].next[j]=-1;
    			}else{
    				if (node[i].k[j]+j<=node[i].num){
    					node[i].to[j]=node[i].to[j+node[i].k[j]];
    					node[i].step[j]=node[i].step[j+node[i].k[j]]+1;
    					node[i].next[j]=node[i].next[j+node[i].k[j]];
    				}else{
    					int tempcnt=i+1;
    					int tempk=node[i].k[j]-(node[i].num-j);
    					while(tempk>node[tempcnt].num){
    						tempk-=node[tempcnt].num;
    						tempcnt++;
    					}
    					node[i].to[j]=tempcnt;
    					node[i].next[j]=tempk;
    					node[i].step[j]=1;
    				}
    			}
    	}
    }
    
    
    inline void Arrest(){
    	printf("Call Cnts:
    ");
    	for (int i=1;i<=cnt;i++){
    		printf("Cnt %d
    ",i);
    		for (int j=1;j<=node[i].num;j++){
    			printf("num=%d index=%d k=%d step=%d toCnt=%d next=%d
    ",j,node[i].index[j],node[i].k[j],node[i].step[j],node[i].to[j],node[i].next[j]);
    		}
    	}	
    }
    
    int main(){
    	scanf("%d",&n);
    	sn=sqrt(n);
    	cnt=n/sn+(n%sn!=0?1:0);
    	int index=0;
    	for(int i=1;i<=n;i++){
    		int temp=0;
    		index++;
    		scanf("%d",&temp);
    		node[(index-1)/sn+1].k[(index-1)%sn+1]=temp;
    		node[(index-1)/sn+1].index[(index-1)%sn+1]=index;
    		node[(index-1)/sn+1].num++;
    	}
    	calc();
    	scanf("%d",&m);
    	for (int i=1;i<=m;i++){
    		//Arrest();
    		int order,j;
    		scanf("%d%d",&order,&j);
    		j++;
    		if (order==1){
    			int icnt=(j-1)/sn+1;
    			int iindex=(j-1)%sn+1;
    			int ans=0;
    			while(iindex!=-1){
    				//printf("icnt %d iindex %d -> Add %d
    ",icnt,iindex,node[icnt].step[iindex]);
    				ans=ans+node[icnt].step[iindex];
    				int tindex=iindex;
    				iindex=node[icnt].next[iindex];
    				icnt=node[icnt].to[tindex];
    			}
    			printf("%d
    ",ans);
    		}else{
    			int k;
    			scanf("%d",&k);
    			calc(j,k);
    		} 
    	}
    	
    	return 0;
    } 



  • 相关阅读:
    .net core读取appsettings.config中文乱码问题
    vs2017错误:当前页面的脚本发生错误
    VS Code中无法识别npm命令
    Visual Studio报错/plugin.vs.js,行:1074,错误:缺少标识符、字符串或数字
    记录一次在生成数据库服务器上出现The timeout period elapsed prior to completion of the operation or the server is not responding.和Exception has been thrown by the target of an invocation的解决办法
    Java集合框架
    java hash表
    Java Dictionary 类存储键值
    java数据结构 栈stack
    java封装
  • 原文地址:https://www.cnblogs.com/WNJXYK/p/4063943.html
Copyright © 2011-2022 走看看