P3203 [HNOI2010]弹飞绵羊

P3203 [HNOI2010]弹飞绵羊

题目描述

详见:P3203 [HNOI2010]弹飞绵羊

solution

这是一道LCT的裸题。

但是我并不想用LCT解决此题(In fact 是不会LCT ~QAQ)

于是我们开始大力分块。

考虑把弹跳装置分块,我们每次需要知道在一个块内需要跳几次以及跳出这个块后到达哪一个节点,这样保证了每一个块的信息不会对其他块的信息产生影响,且我们可以用DP在  O(n)  的时间内预处理出上述信息。

查询时每次跳转到一个之后的块中,沿途统计答案。

修改时由于块与块之间独立,因此直接暴力修改需要修改的一块信息即可。

时间复杂度   O(n\sqrt{n})

Code

#include<bits/stdc++.h>
using namespace std;
const int MAXN=2e5+50;
int a[MAXN],color[MAXN],n,Size;
struct fnode{int x,y; } f[MAXN];
inline int read()
{
	int f=1,x=0; char c=getchar();
	while (c<'0'||c>'9') { if (c=='-') f=-1; c=getchar(); }
	while (c>='0'&&c<='9') { x=(x<<3)+(x<<1)+(c^48); c=getchar(); }
	return x*f;
}
void change(int i)                                                          //求出i位置的信息
{
	if (i+a[i]<=n)
	{
		if (color[i]==color[i+a[i]]) f[i]=(fnode){f[i+a[i]].x,f[i+a[i]].y+1};
		else f[i]=(fnode){i+a[i],1};
	}
	else f[i]=(fnode){-1,1};
}
int main()
{
	n=read(),Size=trunc(sqrt(n));
	for (int i=1;i<=n;i++) a[i]=read(),color[i]=(i-1)/Size+1;
	for (int i=n;i>=1;i--) change(i);                                       //预处理 
	//for (int i=1;i<=n;i++) cout<<i<<":"<<f[i].x<<" "<<f[i].y<<endl;
	
	int Case=read();
	while (Case--)
	{
		int opt=read(),x=read()+1;                                          //标号从0开始 
		if (opt==1)
		{
			int ans=0;
			while (x!=-1) ans+=f[x].y,x=f[x].x;                             //统计答案 
			printf("%d\n",ans);
		}
		else
		{
			int y=read(); a[x]=y;
			for (int i=color[x]*Size;i>=(color[x]-1)*Size+1;i--) change(i); //用与预处理相同的方法暴力修改 
			//for (int i=1;i<=n;i++) cout<<i<<":"<<f[i].x<<" "<<f[i].y<<endl;
		}
	}
	return 0;
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值