BZOJ 2120 数颜色

2120: 数颜色

Time Limit: 6 Sec  Memory Limit: 259 MB
Submit: 8311  Solved: 3419
[Submit][Status][Discuss]

Description

墨墨购买了一套N支彩色画笔(其中有些颜色可能相同),摆成一排,你需要回答墨墨的提问。墨墨会像你发布如下指令: 1、 Q L R代表询问你从第L支画笔到第R支画笔中共有几种不同颜色的画笔。 2、 R P Col 把第P支画笔替换为颜色Col。为了满足墨墨的要求,你知道你需要干什么了吗?

Input

第1行两个整数N,M,分别代表初始画笔的数量以及墨墨会做的事情的个数。第2行N个整数,分别代表初始画笔排中第i支画笔的颜色。第3行到第2+M行,每行分别代表墨墨会做的一件事情,格式见题干部分。

Output

对于每一个Query的询问,你需要在对应的行中给出一个数字,代表第L支画笔到第R支画笔中共有几种不同颜色的画笔。

Sample Input

6 5
1 2 3 4 5 5
Q 1 4
Q 2 6
R 1 2
Q 1 4
Q 2 6

Sample Output

4
4
3
4

HINT

对于100%的数据,N≤10000,M≤10000,修改操作不多于1000次,所有的输入数据中出现的所有整数均大于等于1且不超过10^6。

 

2016.3.2新加数据两组by Nano_Ape

 

 

用pre[i]记录前一个和i相同颜色的球的所在位置

 

询问l到r时,如果pre[i]<l说明在l到i这一段没用和i颜色相同的球,则ans++

 

利用这种思路我们可以。。。分块

每一块内按pre[i]排序

 

BZOJ 2453 维护队列同理

 

#include <bits/stdc++.h>
#define ll long long
#define inf 1e9+10
using namespace std;
inline int read(){
	int x=0;int f=1;char ch=getchar();
	while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
	while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
	return x*f;
}
const int MAXN=1e6+10;
int n,m,block,pre[MAXN],last[MAXN],num,pos[MAXN],a[MAXN],b[MAXN];
inline void sor(int x){
	int l=(x-1)*block+1;int r=min(x*block,n);
	for(int i=l;i<=r;i++) pre[i]=b[i];
	sort(pre+l,pre+r+1);
}
inline int query(int x,int L){
	int l=(x-1)*block+1;int r=min(x*block,n);
	int t=l;
	while(l<=r){
		int mid=(l+r)>>1;
		if(pre[mid]<L) l=mid+1;
		else r=mid-1;
	}
	return l-t;
}
inline void rebuild(int t,int v){
	for(int i=1;i<=n;i++){
		last[a[i]]=0;
	}
	a[t]=v;
	for(int i=1;i<=n;i++){
		int t=b[i];
		b[i]=last[a[i]];
		last[a[i]]=i;
		if(b[i]!=t) sor(pos[i]);
	}
}
inline void build(){
	for(int i=1;i<=n;i++){
		b[i]=last[a[i]];
		last[a[i]]=i;
		pos[i]=(i-1)/block+1;
	}
	for(int i=1;i<=num;i++) sor(i);
}
inline int ask(int L,int R){
	int ans=0;
	for(int i=pos[L]+1;i<pos[R];i++){
		ans+=query(i,L);
	}
	if(pos[L]==pos[R]){
		for(int i=L;i<=R;i++) if(b[i]<L) ans++;
	}
	else{
		for(int i=L;i<=pos[L]*block;i++) if(b[i]<L) ans++;
		for(int i=(pos[R]-1)*block+1;i<=R;i++) if(b[i]<L) ans++;
	}
	return ans;
}
int main(){
	//freopen("All.in","r",stdin);
	//freopen("zem.out","w",stdout);
	n=read();m=read();
	block=(int)sqrt(1.0*n+log(n*2)/log(2));
	if(n%block) num=n/block+1;
	else num=n/block;
	for(int i=1;i<=n;i++){
		a[i]=read();
	}
	build();
	while(m--){
		char op[5];
		scanf("%s",op);
		if(op[0]=='Q'){
			int L=read();int R=read();
			printf("%d\n",ask(L,R));
		}
		else{
			int t=read();int v=read();
			rebuild(t,v);
		}
	}
	return 0;
}

 

posted @ 2018-07-02 21:51  zhangenming  阅读(196)  评论(0编辑  收藏  举报