bzoj2120 数颜色

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。

正解:带修改莫队(分块好像也可以来着。。)

以前一直以为莫队不能带修改,但当修改次数较少的时候,莫队其实也是一个不错的选择。。

只要记录每次询问之前需要的修改,没修改的就修改,不该修改的就撤回,这样就能够做出这题了。。排序时先按左端点所在块排序,再按右端点所在块排序,最后按需要修改的次数排序。具体操作看代码吧。。


//It is made by wfj_2048~
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <vector>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
#define inf 1<<30
#define il inline
#define RG register
#define ll long long
#define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)

using namespace std;

struct node1{ int x,y,last; }r[10010];

struct node2{ int l,r,id,tim,bl,br; }q[10010];

int a[1000010],c[1000010],ans[1000010],last[1000010],n,m,L,R,cnt1,cnt2,Ans,head,block;
char ch[3];

il int gi(){
    RG int x=0,q=0; RG char ch=getchar();
    while ((ch<'0' || ch>'9') && ch!='-') ch=getchar(); if (ch=='-') q=1,ch=getchar();
    while (ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar(); return q ? -x : x;
}

il int cmp(const node2 &a,const node2 &b){
    if (a.bl==b.bl && a.br==b.br) return a.tim<b.tim;
    if (a.bl==b.bl) return a.br<b.br; return a.bl<b.bl;
}

il void change(RG int x,RG int y){
    if (L<=x && x<=R){
	c[a[x]]--; if (c[a[x]]==0) Ans--; a[x]=y;
	c[a[x]]++; if (c[a[x]]==1) Ans++;
    }else a[x]=y;
    return;
}

il void work(){
    n=gi(),m=gi(); block=sqrt(n);
    for (RG int i=1;i<=n;++i) last[i]=a[i]=gi();
    for (RG int i=1;i<=m;++i){
	scanf("%s",ch);
	if (ch[0]=='R'){ RG int x=gi(),col=gi(); r[++cnt1].x=x,r[cnt1].y=col,r[cnt1].last=last[x],last[x]=col; }
	else{
	    RG int l=gi(),r=gi(); q[++cnt2].l=l,q[cnt2].r=r,q[cnt2].id=cnt2;
	    q[cnt2].tim=cnt1,q[cnt2].bl=(l-1)/block+1,q[cnt2].br=(r-1)/block+1;
	}
    }
    sort(q+1,q+cnt2+1,cmp); L=1,R=0,head=0,Ans=0;
    for (RG int i=1;i<=cnt2;++i){
	while (head<q[i].tim) head++,change(r[head].x,r[head].y);
	while (head>q[i].tim) change(r[head].x,r[head].last),head--;
	while (L>q[i].l){ L--,c[a[L]]++; if (c[a[L]]==1) Ans++; }
	while (R<q[i].r){ R++,c[a[R]]++; if (c[a[R]]==1) Ans++; }
	while (L<q[i].l){ c[a[L]]--; if (c[a[L]]==0) Ans--; L++; }
	while (R>q[i].r){ c[a[R]]--; if (c[a[R]]==0) Ans--; R--; }
	ans[q[i].id]=Ans;
    }
    for (RG int i=1;i<=cnt2;++i) printf("%d\n",ans[i]); return;
}

int main(){
    File("color");
    work();
    return 0;
}


posted @ 2017-01-18 21:15  wfj_2048  阅读(130)  评论(0编辑  收藏  举报