BZOJ P2120 数颜色【带修莫队板子】

没错莫队就是这么强!

#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define SG string
#define DB double
using namespace std;
const int Max1=1e6+5;
const int Max2=1e4+5;
struct Node1{
	int X,Y,Id,Time;
}Ask[Max2];
struct Node2{
	int Loc,New,Old;
}Change[Max2];
char CH[2];
int N,M,S,L,R,T,Tot,Ask_Num,Change_Num,A[Max2],B[Max2],Cnt[Max1],Ans[Max1];
bool Cmp(Node1 P,Node1 Q){
	return B[P.X]==B[Q.X]?P.Y<Q.Y:B[P.X]<B[Q.X];
}
void Insert(int X){
	Cnt[X]++;
	if(Cnt[X]==1){
		Tot++;
	}
}
void Delete(int X){
	Cnt[X]--;
	if(Cnt[X]==0){
		Tot--;
	}
}
void Update(int X,int Y){
	if(L<=X&&X<=R){
		Delete(A[X]);
	}A[X]=Y;
	if(L<=X&&X<=R){
		Insert(A[X]);
	}
}
int main(){
	int I,J,K;
	scanf("%d%d",&N,&M);S=sqrt(N);
	for(I=1;I<=N;I++){
		scanf("%d",&A[I]);B[I]=I/S;
	}
	for(I=1;I<=M;I++){
		int X,Y;
		scanf("%s%d%d",CH,&X,&Y);
		if(CH[0]=='Q'){
			Ask[++Ask_Num].X=X;Ask[Ask_Num].Y=Y;Ask[Ask_Num].Id=Ask_Num;Ask[Ask_Num].Time=Change_Num;
		} else {
			Change[++Change_Num].Loc=X;Change[Change_Num].New=Y;Change[Change_Num].Old=A[X];A[X]=Y;
		}
	}
	T=Change_Num;
	sort(Ask+1,Ask+1+Ask_Num,Cmp);
	for(I=1;I<=Ask_Num;I++){
		while(R<Ask[I].Y){
			Insert(A[++R]);
		}
		while(R>Ask[I].Y){
			Delete(A[R--]);
		}
		while(L<Ask[I].X){
			Delete(A[L++]);
		}
		while(L>Ask[I].X){
			Insert(A[--L]);
		}
		while(T>Ask[I].Time){
			Update(Change[T].Loc,Change[T].Old);T--;
		}
		while(T<Ask[I].Time){
			T++;Update(Change[T].Loc,Change[T].New);
		}
		Ans[Ask[I].Id]=Tot;
	}
	for(I=1;I<=Ask_Num;I++){
		printf("%d\n",Ans[I]);
	}
	return 0;
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值