BZOJ2120:数颜色(分块版)

浅谈分块:https://www.cnblogs.com/AKMer/p/10369816.html

题目传送门:https://lydsy.com/JudgeOnline/problem.php?id=2120

树套树做法:https://www.cnblogs.com/AKMer/p/10189008.html

对于每个块维护块内\(pre\)上升的数组即可,每次查找直接\(lower\) \(bound\)一下,其它的跟树套树版的没什么区别。

时间复杂度:\(O(nlog\sqrt{n}+m\sqrt{n}log\sqrt{n})\)

空间复杂度:\(O(n)\)

代码如下:

#include <set>
#include <cmath>
#include <cstdio>
#include <algorithm>
using namespace std;

const int maxn=1e4+5,maxv=1e6+5;;

char s[5];
int n,m,block;
set<int>pos[maxv];
set<int>::iterator it;
int L[105],R[105],f[105][105];
int col[maxn],bel[maxn],pre[maxv],now[maxv];

int read() {
	int x=0,f=1;char ch=getchar();
	for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
	for(;ch>='0'&&ch<='9';ch=getchar())x=x*10+ch-'0';
	return x*f;
}

void build(int id) {
	for(int i=L[id];i<=R[id];i++)
		f[id][i-L[id]+1]=pre[i];
	sort(f[id]+1,f[id]+R[id]-L[id]+2);
}

int main() {
	n=read(),m=read(),block=sqrt(n);
	for(int i=1;i<=n;i++) {
		col[i]=read(),bel[i]=(i-1)/block+1;
		if(pos[col[i]].empty())
			pos[col[i]].insert(0),pos[col[i]].insert(n+1);
		if(bel[i]!=bel[i-1])R[bel[i-1]]=i-1,L[bel[i]]=i;
		pre[i]=now[col[i]],now[col[i]]=i,pos[col[i]].insert(i);
	}R[bel[n]]=n;
	for(int i=1;i<=bel[n];i++)build(i);
	while(m--) {
		scanf("%s",s+1);
		if(s[1]=='Q') {
			int ans=0,l=read(),r=read();
			if(bel[l]==bel[r]) {
				for(int i=l;i<=r;i++)if(pre[i]<l)ans++;
			}
			else {
				for(int i=l;i<=R[bel[l]];i++)if(pre[i]<l)ans++;
				for(int i=L[bel[r]];i<=r;i++)if(pre[i]<l)ans++;
				for(int i=bel[l]+1;i<bel[r];i++)
					ans+=lower_bound(f[i]+1,f[i]+R[i]-L[i]+2,l)-f[i]-1;
			}
			printf("%d\n",ans);
		}
		else {
			int p=read(),c=read(),tmp=col[p],l,r;
			if(pos[c].empty())pos[c].insert(0),pos[c].insert(n+1);
			pos[tmp].erase(pos[tmp].find(p));
			it=pos[tmp].lower_bound(p);
			if(it!=pos[tmp].end()&&it!=pos[tmp].begin())
				r=*it,it--,l=*it,pre[r]=l,build(bel[r]);
			it=pos[c].lower_bound(p);
			if(it!=pos[c].end())pre[*it]=p,build(bel[*it]);
			if(it!=pos[c].begin())it--,pre[p]=*it,build(bel[p]);
			pos[c].insert(p);
			col[p]=c;
		}
	}
	return 0;
}
posted @ 2019-02-14 11:05  AKMer  阅读(144)  评论(0编辑  收藏  举报