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


    2002: [Hnoi2010]Bounce 弹飞绵羊

    Time Limit: 10 Sec  Memory Limit: 259 MB
    Submit: 10629  Solved: 5476
    [Submit][Status][Discuss]

    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

    HINT

    Source

    嗯,LCT还不会,先写一个分块玩玩

    其实分块的思想很简单啦

    将序列分成一块一块的

    同时兼顾修改和查询的复杂度

    每一块的大小就sqrt(n)

    如果后面剩一截不够一块的

    就另开一块

    然后就维护一个店到下一块的步数

    还有到下一块的哪一个点

    修改时就只用改这一块中这个点前面的点

    然后查询就一块一块走

    这样查询和修改的复杂度就兼顾到了O(sqrt(n))啦

    #include<cstdio>
    #include<cmath>
    const int N=200000+5,M=1500;
    int a[N],l[M],r[M],st[N],pt[N],belong[N];
    int cal(int x)
    {
    	int tmp=0;
    	while(1)
    	{
    		tmp+=st[x];
    		if(!pt[x])	break;
    		x=pt[x];
    	}
    	return tmp;
    }
    int main()
    {
    	int n;scanf("%d",&n);int block=sqrt(n);
    	for(int i=1;i<=n;i++)	scanf("%d",&a[i]);
    	int cnt;
    	if(n%block)			cnt=n/block+1;
    	else cnt=n/block;
    	for(int i=1;i<=cnt;i++)
    	l[i]=(i-1)*block+1,r[i]=i*block;
    	r[cnt]=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]>n)	st[i]=1;
    		else if(belong[i]==belong[i+a[i]])	st[i]=st[i+a[i]]+1,pt[i]=pt[i+a[i]];
    		else st[i]=1,pt[i]=i+a[i];
    	}
    	int m,u,v,q;
    	scanf("%d",&m);
    	for(int i=1;i<=m;i++)
    	{
    		scanf("%d %d",&u,&v);v++;
    		if(u==1)	printf("%d
    ",cal(v));
    	 	else 
    	 	{
    	 		scanf("%d",&q);a[v]=q;
    			 for(int i=v;i>=l[belong[v]];i--)
    			 if(belong[i]==belong[i+a[i]])	st[i]=st[i+a[i]]+1,pt[i]=pt[i+a[i]];
    		   	 else st[i]=1,pt[i]=i+a[i];
    	 	} 
    	}
    	return 0;
    }


    LCT未完待续。。。。。。



  • 相关阅读:
    CocoStudio UI 编辑器的使用
    脚本AI与脚本引擎
    Android 开发问题集合
    cocos2d-x之 CCSpriteBatchNode 用法总结
    图解VS2010打包全过程
    如何写详细设计文档
    母函数(Generating function)详解 — TankyWoo
    【DP_区间DP专辑】 zeroclock
    【DP_概率DP专辑】【from zeroclock's blog】
    【DP_树形DP专辑】【from zeroclock's blog】
  • 原文地址:https://www.cnblogs.com/Brian551/p/7353028.html
Copyright © 2011-2022 走看看