关闭

bzoj2002【HNOI2010】Bounce 弹飞绵羊

标签: bzoj分块LCT
2388人阅读 评论(0) 收藏 举报
分类:

2002: [Hnoi2010]Bounce 弹飞绵羊

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



方法一:分块

很巧妙的分块。

每个点记录跳出所在块的步数以及跳出去的位置,每次修改暴力修改所在块的信息。

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#define F(i,j,n) for(int i=j;i<=n;i++)
#define D(i,j,n) for(int i=j;i>=n;i--)
#define ll long long
#define maxn 200005
using namespace std;
int n,m,block;
int a[maxn],num[maxn],f[maxn],p[maxn];
inline int read()
{
	int x=0,f=1;char ch=getchar();
	while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
	while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
	return x*f;
}
int calc(int x)
{
	int ret=0;
	for(;x;x=p[x]) ret+=f[x];
	return ret;
}
int main()
{
	n=read();
	block=round(sqrt(n));
	F(i,1,n) a[i]=read(),num[i]=(i-1)/block+1;
	D(i,n,1)
	{
		if (i+a[i]>n) f[i]=1,p[i]=0;
		else if (num[i]==num[i+a[i]]) f[i]=f[i+a[i]]+1,p[i]=p[i+a[i]];
		else f[i]=1,p[i]=i+a[i];
	}
	m=read();
	while (m--)
	{
		int opt=read(),x=read()+1;
		if (opt==1) printf("%d\n",calc(x));
		else
		{
			a[x]=read();
			D(i,x,(num[x]-1)*block+1)
			{
				if (i+a[i]>n) f[i]=1,p[i]=0;
				else if (num[i]==num[i+a[i]]) f[i]=f[i+a[i]]+1,p[i]=p[i+a[i]];
				else f[i]=1,p[i]=i+a[i];
			}
		}
	}
	return 0;
}


方法二:LCT

维护一下子树的大小,注意cut操作里要splay,因为x和y的父子关系不确定,否则会出错。

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#define F(i,j,n) for(int i=j;i<=n;i++)
#define D(i,j,n) for(int i=j;i>=n;i--)
#define ll long long
#define N 200005
using namespace std;
int n,m,nxt[N],st[N];
struct LCT
{
	int ch[N][2],fa[N],sz[N];bool rev[N];
	inline bool isroot(int x)
	{
		return (ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x);
	}
	inline void pushdown(int x)
	{
		if (!rev[x]) return;
		rev[ch[x][0]]^=1;rev[ch[x][1]]^=1;
		swap(ch[x][0],ch[x][1]);
		rev[x]=0;
	}
	inline void pushup(int x)
	{
		sz[x]=sz[ch[x][0]]+sz[ch[x][1]]+1;
	}
	void rotate(int x)
	{
		int y=fa[x],z=fa[y],l=ch[y][1]==x,r=l^1;
		if (!isroot(y)) ch[z][ch[z][1]==y]=x;
		fa[x]=z;fa[y]=x;fa[ch[x][r]]=y;
		ch[y][l]=ch[x][r];ch[x][r]=y;
		pushup(y);pushup(x);
	}
	void splay(int x)
	{
		int top=0;st[++top]=x;
		for(int i=x;!isroot(i);i=fa[i]) st[++top]=fa[i];
		D(i,top,1) pushdown(st[i]);
		while (!isroot(x))
		{
			int y=fa[x],z=fa[y];
			if (!isroot(y))
			{
				if (ch[y][0]==x^ch[z][0]==y) rotate(x);
				else rotate(y);
			}
			rotate(x);
		}
	}
	void access(int x)
	{
		int t=0;
		while (x)
		{
			splay(x);
			ch[x][1]=t;
			t=x;x=fa[x];
		}
	}
	inline void moveroot(int x)
	{
		access(x);splay(x);rev[x]^=1;
	}
	inline void link(int x,int y)
	{
		moveroot(x);fa[x]=y;
	}
	inline void cut(int x,int y)
	{
		moveroot(x);access(y);splay(y);ch[y][0]=fa[x]=0;
	}
	inline int query(int x)
	{
		moveroot(n+1);access(x);splay(x);
		return sz[ch[x][0]];
	}
}lct;
inline int read()
{
	int x=0,f=1;char ch=getchar();
	while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
	while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
	return x*f;
}
int main()
{
	n=read();
	F(i,1,n)
	{
		int x=read();
		nxt[i]=lct.fa[i]=min(i+x,n+1);
		lct.sz[i]=1;
	}
	m=read();
	while (m--)
	{
		int opt=read(),x=read()+1;
		if (opt==1) printf("%d\n",lct.query(x));
		else
		{
			int y=read(),t=min(x+y,n+1);
			lct.cut(x,nxt[x]);lct.link(x,t);nxt[x]=t;
		}
	}
	return 0;
}


0
0
查看评论

BZOJ 2002 [Hnoi2010]Bounce 弹飞绵羊 LCT

BZOJ 2002 [Hnoi2010]Bounce 弹飞绵羊 LCT
  • wzq_QwQ
  • wzq_QwQ
  • 2015-08-10 13:41
  • 1557

bzoj2002:[Hnoi2010]Bounce 弹飞绵羊

思路:动态树。把每个装置看成点,能弹到的装置连边,能弹飞的装置连到n+1号点,每个点点权设为1,这样问几次弹飞就可以转化为该点到n+1号点的路径的点权和。 #include #include #include #include const int maxn=200010; using namesp...
  • thy_asdf
  • thy_asdf
  • 2015-06-22 19:58
  • 506

[bzoj2002] [Hnoi2010]Bounce 弹飞绵羊

Problem link[Hnoi2010]Bounce 弹飞绵羊Description某天,Lostmonkey发明了一种超级弹力装置,为了在他的绵羊朋友面前显摆,他邀请小绵羊一起玩个游戏。游戏一开始,Lostmonkey在地上沿着一条直线摆上n个装置,每个装置设定初始弹力系数ki,当绵羊达到第i...
  • u011056504
  • u011056504
  • 2016-08-13 21:55
  • 297

BZOJ 2002 Bounce 弹飞绵羊(分块|暴力|)(困难)

将序列分块,每块sqrt(n)个。 在每个块中维护f[i],to[i] f[i] 表示跳几次可以跳出所在块 to[i] 表示跳出所在块后到达的位置。 在查询时,我们O(sqrt(n))的时间进行“整块”的模拟,可以得到结果。
  • kaisa158
  • kaisa158
  • 2015-08-03 22:20
  • 580

bzoj2002: [Hnoi2010]Bounce 弹飞绵羊

链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2002 题意:中文题。。 分析:先将这个数组分块,每块大小为sqrt(n),然后设定f[i]表示从i出发到第一个和i不同块的点所需的步数,nex[i]表示那个第一个和i不同块的点的位置。然后我...
  • Fsss_7
  • Fsss_7
  • 2015-12-31 01:38
  • 203

BZOJ 2002 HNOI2010 弹飞绵羊 分块

题目大意及LCT版本题解:见 http://blog.csdn.net/popoqqq/article/details/38849471 今天手滑用分块又重写了一遍这道题0.0 分块就是短啊 将弹簧分为√n块 对于每个弹簧 我们记录一下从这个弹簧出发直到弹到块外为止的弹跳次数及落点 ...
  • PoPoQQQ
  • PoPoQQQ
  • 2014-10-21 17:22
  • 1892

[BZOJ2002][HNOI2010]弹飞绵羊(LCT)

写作是与自己的灵魂交谈,借此把外在的生命转变成内在的心灵财富。
  • Clove_unique
  • Clove_unique
  • 2016-03-27 14:38
  • 1164

bzoj 2002 Bounce 弹飞绵羊

2002: [Hnoi2010]Bounce 弹飞绵羊 Time Limit: 10 Sec  Memory Limit: 259 MB Submit: 6894  Solved: 3610 [Submit][St...
  • clover_hxy
  • clover_hxy
  • 2016-03-21 19:40
  • 238

动态树-LCT-bzoj2002弹飞绵羊

我的第一篇博客给LCT(Link-Cut Tree)^_动态树要求我们维护一个由若干棵子结点无序的有根树组成的森林。 要求这个数据结构支持对树的分割,合并,对某个点到它的根的路径的某些操作, 以及对某个点的子树进行的某些操作。其中解决问题使用最多的是LCT,这里就主要介绍一下LCT吧。其实动态树主题...
  • Frods
  • Frods
  • 2016-08-18 19:44
  • 726

HYSBZ - 2002 :Bounce 弹飞绵羊 (分块算法)

HYSBZ - 2002 :Bounce 弹飞绵羊 (分块算法) 神奇的分块
  • f2935552941
  • f2935552941
  • 2017-10-04 00:35
  • 72
    个人资料
    • 访问:739367次
    • 积分:11556
    • 等级:
    • 排名:第1588名
    • 原创:417篇
    • 转载:3篇
    • 译文:0篇
    • 评论:45条
    云中谁寄锦书来