BZOJ 2002([Hnoi2010]Bounce 弹飞绵羊-LCT)

2002: [Hnoi2010]Bounce 弹飞绵羊

Time Limit: 10 Sec   Memory Limit: 259 MB
Submit: 5212   Solved: 2774
[ 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

参考《QTREE解法的一些研究》

kuangbin的代码





#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<functional>
#include<iostream>
#include<cmath>
#include<cctype>
#include<ctime>
using namespace std;
#define For(i,n) for(int i=1;i<=n;i++)
#define Fork(i,k,n) for(int i=k;i<=n;i++)
#define Rep(i,n) for(int i=0;i<n;i++)
#define ForD(i,n) for(int i=n;i;i--)
#define RepD(i,n) for(int i=n;i>=0;i--)
#define Forp(x) for(int p=pre[x];p;p=next[p])
#define Forpiter(x) for(int &p=iter[x];p;p=next[p])  
#define Lson (x<<1)
#define Rson ((x<<1)+1)
#define MEM(a) memset(a,0,sizeof(a));
#define MEMI(a) memset(a,127,sizeof(a));
#define MEMi(a) memset(a,128,sizeof(a));
#define INF (2139062143)
#define F (100000007)
#define MAXN (200000+10)
#define MAXM (100000+10) 
typedef long long ll;
ll mul(ll a,ll b){return (a*b)%F;}
ll add(ll a,ll b){return (a+b)%F;}
ll sub(ll a,ll b){return (a-b+(a-b)/F*F+F)%F;}
void upd(ll &a,ll b){a=(a%F+b%F)%F;}

int n,m;

class Splay
{
public:
	int father[MAXN],siz[MAXN];
	int ch[MAXN][2];
	bool root[MAXN];
	void mem(int n)
	{
		MEM(father) MEM(siz) MEM(root)
		For(i,n+1) siz[i]=1,root[i]=1;root[0]=1;
		MEM(ch) 
		 
	}
	void maintain(int x)
	{
		siz[x]=siz[ch[x][0]]+siz[ch[x][1]]+1;
	}
	void rotate(int x)
	{
		int y=father[x],kind=ch[y][1]==x;
		ch[y][kind]=ch[x][!kind];
		if (ch[y][kind]) {
			father[ch[y][kind]]=y;
		}
		father[x]=father[y];
		father[y]=x;
		ch[x][!kind]=y;
		if (root[y])
		{
			root[x]=1;root[y]=0;
		}
		else
		{
			ch[father[x]][ ch[father[x]][1]==y ] = x;
		}
		maintain(y);maintain(x);
	}
	void splay(int x)
	{
		while(!root[x])
		{
			int y=father[x];
			int z=father[y];
			if (root[y]) rotate(x);
			else if ( (ch[y][1]==x)^(ch[z][1]==y) )
			{
				rotate(x); rotate(x);
			} 
			else 
			{
				rotate(y); rotate(x);
			}
		}
	}
	
	int access(int x)
	{
		int y=0;
		do
		{
			splay(x);
			if (ch[x][1]) root[ch[x][1]]=1; root[ch[x][1]=y]=0;		
			maintain(x);
			y = x;
			x=father [ x]; 
		} while (x) ;
		return y;
	}
	
}S;


int main()
{
//	freopen("bzoj2002.in","r",stdin);
//	freopen(".out","w",stdout);
	cin>>n;
	S.mem(n);
	For(i,n) 
	{
		scanf("%d",&S.father[i]);
		S.father[i]+=i;
		if (S.father[i]>n) S.father[i]=n+1;
	}
	cin>>m;
	For(i,m)
	{
		int p;
		scanf("%d",&p);
		if (p==1)
		{
			int x;
			scanf("%d",&x);x++;
			S.access(x);
			S.splay(x);
			printf("%d\n",S.siz[S.ch[x][0]]);
			
		} else {
			int x,k;
			scanf("%d%d",&x,&k);x++;
			k+=x;
			if (k>n) k=n+1;
			
			S.access(x);
			S.splay(x);
			S.father[S.ch[x][0]]=S.father[x];
			S.father[x]=0;
			S.root[S.ch[x][0]]=1;
			S.ch[x][0]=0;
			S.maintain(x);
			S.father[x]=k; 
			
		}
	}
	 
	
	
	return 0;
}


8.28  删除了没有多余的代码

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<functional>
#include<iostream>
#include<cmath>
#include<cctype>
#include<ctime>
using namespace std;
#define For(i,n) for(int i=1;i<=n;i++)
#define Fork(i,k,n) for(int i=k;i<=n;i++)
#define Rep(i,n) for(int i=0;i<n;i++)
#define ForD(i,n) for(int i=n;i;i--)
#define RepD(i,n) for(int i=n;i>=0;i--)
#define Forp(x) for(int p=pre[x];p;p=next[p])
#define Forpiter(x) for(int &p=iter[x];p;p=next[p])  
#define Lson (x<<1)
#define Rson ((x<<1)+1)
#define MEM(a) memset(a,0,sizeof(a));
#define MEMI(a) memset(a,127,sizeof(a));
#define MEMi(a) memset(a,128,sizeof(a));
#define INF (2139062143)
#define F (100000007)
#define MAXN (200000+10)
#define MAXM (100000+10) 
typedef long long ll;
ll mul(ll a,ll b){return (a*b)%F;}
ll add(ll a,ll b){return (a+b)%F;}
ll sub(ll a,ll b){return (a-b+(a-b)/F*F+F)%F;}
void upd(ll &a,ll b){a=(a%F+b%F)%F;}

int n,m;

class Splay
{
public:
	int father[MAXN],siz[MAXN];
	int ch[MAXN][2];
	bool root[MAXN];
	void mem(int n)
	{
		MEM(father) MEM(siz) MEM(root)
		For(i,n+1) siz[i]=1,root[i]=1;root[0]=1;
		MEM(ch) 
		 
	}
	void maintain(int x)
	{
		siz[x]=siz[ch[x][0]]+siz[ch[x][1]]+1;
	}
	void rotate(int x)
	{
		int y=father[x],kind=ch[y][1]==x;
		ch[y][kind]=ch[x][!kind];
		if (ch[y][kind]) {
			father[ch[y][kind]]=y;
		}
		father[x]=father[y];
		father[y]=x;
		ch[x][!kind]=y;
		if (root[y])
		{
			root[x]=1;root[y]=0;
		}
		else
		{
			ch[father[x]][ ch[father[x]][1]==y ] = x;
		}
		maintain(y);maintain(x);
	}
	void splay(int x)
	{
		while(!root[x])
		{
			int y=father[x];
			int z=father[y];
			if (root[y]) rotate(x);
			else if ( (ch[y][1]==x)^(ch[z][1]==y) )
			{
				rotate(x); rotate(x);
			} 
			else 
			{
				rotate(y); rotate(x);
			}
		}
	}
	
	int access(int x)
	{
		int y=0;
		do
		{
			splay(x);
			if (ch[x][1]) root[ch[x][1]]=1;
			ch[x][1]=y;
			if (y) root[y]=0;		
			maintain(x);
			y = x;
			x=father [x]; 
		} while (x) ;
		return y;
	}
	void cut(int x)
	{
		access(x);
		splay(x);
		
		father[ch[x][0]]=0;
		root[ch[x][0]]=1;
		ch[x][0]=0;
		maintain(x);
	}
	
	void join(int x,int w)
	{
		father[x]=w;
	}
	
}S;


int main()
{
//	freopen("bzoj2002.in","r",stdin);
//	freopen(".out","w",stdout);
	cin>>n;
	S.mem(n);
	For(i,n) 
	{
		scanf("%d",&S.father[i]);
		S.father[i]+=i;
		if (S.father[i]>n) S.father[i]=n+1;
	}
	cin>>m;
	For(i,m)
	{
		int p;
		scanf("%d",&p);
		if (p==1)
		{
			int x;
			scanf("%d",&x);x++;
			S.access(x);
			S.splay(x);
			printf("%d\n",S.siz[S.ch[x][0]]);
			
		} else {
			int x,k;
			scanf("%d%d",&x,&k);x++;
			k+=x;
			if (k>n) k=n+1;
			
			S.cut(x);
			S.join(x,k);
			
			
		}
	}
	 
	
	
	return 0;
}







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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值