bzoj 2120 数颜色

题目描述

墨墨购买了一套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≤10000,M≤10000,修改操作不多于1000次,所有的输入数据中出现的所有整数均大于等于1且不超过10^6。

来源:bzoj2120

题解:

带修改的莫队 luogu wa一个点,bzoj A 了。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define maxn 1000005
using namespace std;

int n,m,a[maxn],cp[maxn],c[maxn],cnt,tim,ans,t,L,R;

struct Query{
    int l,r,id,pos,ans,t;
}q[maxn];

struct Change{
    int x,y,bf;
}r[maxn];

bool cmp_id(Query a,Query b){
    return a.id<b.id;
}

bool cmp(Query a,Query b){
    if(a.pos!=b.pos)return a.pos<b.pos;
    if(a.r!=b.r)return a.r<b.r;
    return a.t<b.t;
}

void timdel(int x,int to){
    if(L<=x&&x<=R){
        if(c[a[x]]==1)ans--;c[a[x]]--;
        a[x]=to;if(c[a[x]]==0)ans++;c[a[x]]++;
    }else{
        a[x]=to;
    }
}

void add(int x){
    if(c[a[x]]==0)ans++;
    c[a[x]]++;
}

void del(int x){
    if(c[a[x]]==1)ans--;
    c[a[x]]--;    
}

void slove(){
    L=1;R=0;t=0;
    sort(q+1,q+cnt+1,cmp);
    for(int i=1;i<=n;i++){
        while(t>q[i].t)timdel(r[t].x,r[t].bf),t--;
        while(t<q[i].t)t++,timdel(r[t].x,r[t].y);
        while(L<q[i].l)del(L++);
        while(L>q[i].l)add(--L);
        while(R>q[i].r)del(R--);
        while(R<q[i].r)add(++R);
        q[i].ans=ans;
    }
}

int main(){
    scanf("%d%d",&n,&m);int size=(int)sqrt(n);
    for(int i=1;i<=n;i++)scanf("%d",&a[i]),cp[i]=a[i];
    for(int i=1;i<=m;i++){
        char s[2];int x,y;
        cin>>s>>x>>y;
        if(s[0]=='Q'){
            q[++cnt].l=x;q[cnt].r=y;q[cnt].id=cnt;
            q[cnt].t=tim;q[cnt].pos=(x-1)/size+1; 
        }else{
            r[++tim].x=x;r[tim].y=y;r[tim].bf=cp[x];
            cp[x]=y;
        }
    }
    slove();
    sort(q+1,q+cnt+1,cmp_id);
    for(int i=1;i<=cnt;i++)printf("%d\n",q[i].ans);
    return 0;
}

 

posted @ 2017-09-21 10:30  ANhour  阅读(199)  评论(0编辑  收藏  举报