LOJ#6284 数列分块入门8 分块

题目链接:传送门

分块,对于每个块维护一个值,表示是不是整个块值都相同,如果是,记录这个值。
为了方便,若一个块里面数的值都相同,叫做“整块”
然后每次查询,如果是整块就判断一下这个值是否与 c c c相等,不是整块就扫一遍。
修改就边角暴莉,中间修改块的值就珂以了。
这样应该是均摊 O ( n n ) O(n\sqrt n) O(nn )的,虽然我不会证, 但是珂以感性 理解一下:
首先修改是每次 O ( n ) O(\sqrt n) O(n )的。
因为询问完就要修改,所以如果有一次修改是 O ( n ) O(n) O(n)的,即扫过了整个序列,那么修改会教他做人 让除了首尾两个块之外的所有块都变成整块。
在整块上的查询珂以 O ( 1 ) O(1) O(1),所以时间复杂度到不了 O ( n 2 ) . O(n^2). O(n2).

代码

#include<stdio.h>
#include<cstring>
#include<algorithm>
#include<math.h>
#include<vector>
#define re register int
#define rl register ll
#define lowbit(x) x&(-x)
using namespace std;
typedef long long ll;
int read() {
	re x=0,f=1;
	char ch=getchar();
	while(ch<'0' || ch>'9') {
		if(ch=='-')	f=-1;
		ch=getchar();
	}
	while(ch>='0' && ch<='9') {
		x=10*x+ch-'0';
		ch=getchar();
	}
	return x*f;
}
inline void write(int x) {
	if(x>9)	write(x/10);
	putchar(x%10+'0');
}
namespace I_Love {

const int Size=100005;
int n,siz,a[Size],blk[Size],belong[Size];
void Baoli_Update(int l,int r,int v) {
	int b=belong[l];
	if(blk[b]) {
		int le=(b-1)*siz+1;
		int ri=min(b*siz,n);
		for(re i=le; i<l; i++)	a[i]=blk[b];
		for(re i=l; i<=r; i++)	a[i]=v;
		for(re i=r+1; i<=ri; i++)	a[i]=blk[b];
		blk[b]=0;
	} else {
		for(re i=l; i<=r; i++) {
			a[i]=v;
		}
	}
}
int Baoli_Query(int l,int r,int v) {
	int b=belong[l];
	int ans=0;
	if(blk[b]) {
		if(blk[b]==v)	return r-l+1;
	} else {
		for(re i=l; i<=r; i++) {
			if(a[i]==v) {
				ans++;
			}
		}
	}
	return ans;
}
void Fujibayashi_Ryou() {
	n=read();
	siz=sqrt(n);
	for(re i=1; i<=n; i++) {
		a[i]=read();
		belong[i]=(i-1)/siz+1;
	}
	int B=belong[n];
	for(re i=1; i<=B; i++) {
		int le=(i-1)*siz+1;
		int ri=min(i*siz,n);
		int val=a[le];
		bool flag=false;
		for(re j=le+1; j<=ri; j++) {
			if(a[j]!=val) {
				flag=true;
				break;
			}
		}
		if(!flag)	blk[i]=val;
	}
	for(re i=1; i<=n; i++) {
		int l=read();
		int r=read();
		int c=read();
		int bl=belong[l];
		int br=belong[r];
		if(bl==br) {
			printf("%d\n",Baoli_Query(l,r,c));
			Baoli_Update(l,r,c);
		} else {
			int rb=bl*siz,lb=(br-1)*siz+1;
			int ans=Baoli_Query(l,rb,c)+Baoli_Query(lb,r,c);
			for(re i=bl+1; i<br; i++) {
				int le=(i-1)*siz+1;
				int ri=min(siz*i,n);
				if(blk[i]) {
					if(blk[i]==c) {
						ans+=ri-le+1;
					}
				} else {
					ans+=Baoli_Query(le,ri,c);
				}
			}
			printf("%d\n",ans);
			Baoli_Update(l,rb,c);
			Baoli_Update(lb,r,c);
			for(re i=bl+1; i<br; i++) {
				blk[i]=c;
			}
		}
	}
}

}
int main() {
	I_Love::Fujibayashi_Ryou();
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值