首页 > 其他分享 >[DS记录] P3203 [HNOI2010] 弹飞绵羊

[DS记录] P3203 [HNOI2010] 弹飞绵羊

时间:2023-08-22 21:55:18浏览次数:36  
标签:BB int 复杂度 pos sqrt lk HNOI2010 P3203 弹飞

题目传送门

虽然是 \(\rm LCT\) 板子,但用来做分块入门

如果没有修改操作,可以 \(O(n)\) 求出每个点的答案

对于每个块里的点,预处理出它跳出这个块的步数,那么查询时就可以 \(O(1)\) 跳过这些块,查询的复杂度 \(O(\sqrt{n})\)

修改一个点时,也就是 \(O(B)\) 暴力修改即可

令 \(B=\sqrt{n}\),可以达到 \(O(\sqrt{n})\) 的时间复杂度

#include<bits/stdc++.h>
using namespace std;

const int N=200010,BB=5010;

int n,m,e[N];
int B,t,L[BB],R[BB],pos[N],f[N],lk[N];

void prework()
{
	B=sqrt(n);  t=n/B;
	for(int i=1; i<=t; i++)
		L[i]=(i-1)*B+1,R[i]=i*B;
	if(R[t]<n)
		t++,L[t]=R[t-1]+1,R[t]=n;
	for(int i=1; i<=t; i++)
	{
		for(int j=R[i]; j>=L[i]; j--)
		{
			pos[j]=i;
			if(j+e[j]>R[i])
				f[j]=1,lk[j]=j+e[j];
			else
				f[j]=f[j+e[j]]+1,lk[j]=lk[j+e[j]];
		} 
	}
}

void change(int x,int v)
{
	int p=pos[x];  e[x]=v;
	for(int i=R[p]; i>=L[p]; i--)
	{
		if(i+e[i]>R[p])
			f[i]=1,lk[i]=i+e[i];
		else
			f[i]=f[i+e[i]]+1,lk[i]=lk[i+e[i]];
	}
}

int ask(int x)
{
	int p=pos[x],res=f[x];
	for(int i=p+1,cur=lk[x]; i<=t; i++)
	{
		res+=f[cur];
		cur=lk[cur];
	}
	return res;
}

int main()
{
	scanf("%d",&n);
	for(int i=1; i<=n; i++)
		scanf("%d",&e[i]);
		
	prework();
	
	scanf("%d",&m);
	while(m--)
	{
		int op,s,k;
		scanf("%d%d",&op,&s);
		
		if(op==1)
			printf("%d\n",ask(++s));
		else
		{
			scanf("%d",&k);
			change(++s,k);
		}
	}

	return 0;
}

标签:BB,int,复杂度,pos,sqrt,lk,HNOI2010,P3203,弹飞
From: https://www.cnblogs.com/xishanmeigao/p/17649790.html

相关文章

  • luogu P3203 [HNOI2010] 弹飞绵羊 题解
    题目传送门:P3203[HNOI2010]弹飞绵羊题意\(n\)个数,满足\(i<a_i≤N+1\),\(m\)次下面两种操作修改一个数\(a_i\)从\(x\)开始跳,\(x=a_x\),几次能够跳出序列\(n\leq2*10^5,m<10^5\)分析数据范围比较大,单纯搜索模拟肯定会T,那么考虑每次让他跳一段就......
  • Unity3D 使用带刚体组件的预制体配合脚本自动生成一面墙时上层墙体被弹飞
    异常效果如下图所示:预制体是一个正方体(Cube),其参数设置如下图所示:控制墙面生成的C#脚本如下所示:usingSystem.Collections;usingSystem.Collections.Generic;usingUnityEngine;publicclassWall:MonoBehaviour{publicTransformbrick;//Usethisf......
  • P3205 [HNOI2010]合唱队
    P3205[HNOI2010]合唱队区间DP——取一端思:根据题意我们发现,每次排队的时候,会出现两种情况当前排入的人(即初始队列最后一人)比初始队列中前一个人矮,排到最左边当前排入的人(同上)比初始队列中前一个人高,排到最右边可从初始队列最后一人切入。设置状态:\(f[l][r][0/1]\)......
  • P3205 [HNOI2010]合唱队(区间dp+方案数)
    P3205[HNOI2010]合唱队-洛谷|计算机科学教育新生态(luogu.com.cn)这道题大区间包括小区间,每加一个人都会让区间更大;考虑区间DP:对于区间[i~j],这段区间最新......
  • P3203做题记录
    一种更简单的想法,只用用分块思想(或者根号分治?)不用分块。先考虑暴力怎么做:修改直接改,查询不停跳下一个点。但这样会被卡到\(O(n^2)\)。考虑分块思想优化:如果保证每次至少......
  • P3205 [HNOI2010]合唱队
    P3205[HNOI2010]合唱队题目大意:一个排队方式,共\(n\)个人($n\leq1000$),如果当前人的身高大于前一个,那么将这个人排在前一个人右边,如果当前人身高小于前一个人,那么......
  • P3205 [HNOI2010]合唱队
    思路我们用\(f_{i,j,0}\)表示当前\([i,j]\)的人都已经入队了,并且\(i\)是从左边进的(\(0\)),或\(j\)是从右边进的(\(1\))。具体细节见代码。代码#include<iostream>#includ......