1. 程式人生 > >[國家集訓隊]數顏色 / 維護佇列 洛谷p1903

[國家集訓隊]數顏色 / 維護佇列 洛谷p1903

題目描述

墨墨購買了一套N支彩色畫筆(其中有些顏色可能相同),擺成一排,你需要回答墨墨的提問。墨墨會向你釋出如下指令:

1、 Q L R代表詢問你從第L支畫筆到第R支畫筆中共有幾種不同顏色的畫筆。

2、 R P Col 把第P支畫筆替換為顏色Col。

為了滿足墨墨的要求,你知道你需要幹什麼了嗎?

輸入輸出格式

輸入格式:

 

第1行兩個整數N,M,分別代表初始畫筆的數量以及墨墨會做的事情的個數。

第2行N個整數,分別代表初始畫筆排中第i支畫筆的顏色。

第3行到第2+M行,每行分別代表墨墨會做的一件事情,格式見題幹部分。

 

輸出格式:

 

對於每一個Query的詢問,你需要在對應的行中給出一個數字,代表第L支畫筆到第R支畫筆中共有幾種不同顏色的畫筆。

 

輸入輸出樣例

輸入樣例#1: 複製

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

輸出樣例#1: 複製

4
4
3
4

說明

對於100%的資料,N≤50000,M≤50000,所有的輸入資料中出現的所有整數均大於等於1且不超過10^6。

本題可能輕微卡常數

來源:bzoj2120

本題資料為洛谷自造資料,使用CYaRon耗時5分鐘完成資料製作。

 

#include<bits/stdc++.h>
#define f(i,l,r) for(i=(l);i<=(r);i++)
using namespace std;
const int MAXN=5000000;
int n,m;
int Base,qnum,cnum;
int a[MAXN],Bel[MAXN];
int lcur=1,rcur,cur;
int ans[MAXN],res;
int num[MAXN];
struct Que{
	int l,r,pre,id;
}q[MAXN];
struct Cha{
	int pos,w;
}c[MAXN];
string s;
bool cmp(Que a,Que b)
{
	if(Bel[a.l]==Bel[b.l]&&Bel[a.r]==Bel[b.r]) return a.pre<b.pre;
	if(Bel[a.l]==Bel[b.l]) return a.r<b.r;
	return a.l<b.l;
}
void add(int pos)
{
	if(++num[a[pos]]==1) res++;
}
void del(int pos)
{
	if(--num[a[pos]]==0) res--;
}
inline void work(int cpos,int qpos)
{
	if(c[cpos].pos>=q[qpos].l&&c[cpos].pos<=q[qpos].r){
		if(--num[a[c[cpos].pos]]==0) res--;
		if(++num[c[cpos].w]==1) res++;
	}
	swap(a[c[cpos].pos],c[cpos].w);
}
int main()
{
	ios::sync_with_stdio(false);
	int i,j;
	cin>>n>>m;
	Base=sqrt(n);
	f(i,1,n){
		cin>>a[i];
		Bel[i]=(i-1)/Base+1;
	}
	f(i,1,m){
		cin>>s;
		if(s=="Q"){
			qnum++;
			cin>>q[qnum].l>>q[qnum].r;
			q[qnum].id=qnum;
			q[qnum].pre=cnum;
		//	cout<<q[qnum].l<<"  "<<q[qnum].r<<"GG"<<endl;
		}
		else{
			cnum++;
			cin>>c[cnum].pos>>c[cnum].w;
		}
	}
//	f(i,1,qnum) cout<<q[i].l<<" "<<q[i].r<<endl;
	sort(q+1,q+1+qnum,cmp);
	f(i,1,qnum){
		while(lcur<q[i].l) del(lcur++);
		while(lcur>q[i].l) add(--lcur);
		while(rcur<q[i].r) add(++rcur);
		while(rcur>q[i].r) del(rcur--);
		while(cur<q[i].pre) work(++cur,i);
		while(cur>q[i].pre) work(cur--,i);
		ans[q[i].id]=res;
	//	cout<<q[i].id<<" "<<q[i].l<<" "<<q[i].r<<" "<<res<<"GGG"<<endl;
	}
	f(i,1,qnum){
		cout<<ans[i]<<endl;
	}
	return 0;
}