[国家集训队]数颜色 / 维护队列(带修莫队)

题意:

       对给定的序列,回答m个询问,Q:询问l到r中不同的颜色数量,R:将下标为x的颜色改为y

题解:

       带修莫队,相对普通的莫队,加多了一个关键字排序

#include<bits/stdc++.h>
#define num ch-'0'
#define pn putchar('\n')
using namespace std;
template<typename T>
void read(T &res) {
    bool flag=false;char ch;
    while(!isdigit(ch=getchar()))(ch=='-')&&(flag=true);
    for(res=num;isdigit(ch=getchar());res=res*10+num);
    flag&&(res=-res);
}
template<typename T>
void write(T x) {
    if(x<0) putchar('-'),x=-x;
    if(x>9) write(x/10);
    putchar(x%10+'0');
}
const int maxn=50010;
const int M=50010;
int n,m;
int qu_num,op_num;
int lst[maxn],col[maxn],blo[maxn],cnt[1000010],res[M];
struct query{
    int l,r,t,pos;
    bool  operator <(const query &a) const {
        return blo[a.l]==blo[l]?(blo[a.r]==blo[r]?t<a.t:blo[r]<blo[a.r]):blo[l]<blo[a.l];
    }
}qu[M];
struct oper {
    int x,lst,now;
}op[M];
int main()
{
    read(n),read(m);
    int q=pow(n,0.666666);
    for(int i=1;i<=n;i++)
        read(col[i]),blo[i]=(i-1)/q+1,lst[i]=col[i];
    int x,y;
    for(int i=1;i<=m;i++) {
        char ch[5];
        scanf("%s",ch);
        scanf("%d%d",&x,&y);
        if(ch[0]=='Q')
            qu[++qu_num].l=x,qu[qu_num].r=y,qu[qu[qu_num].pos=qu_num].t=op_num;
        else
            op[++op_num].x=x,op[op_num].lst=lst[x],op[op_num].now=y,lst[x]=y;
    }
    sort(qu+1,qu+1+qu_num);
    int l=0,r=0,t=0,ans=0;
    for(int i=1;i<=qu_num;i++) {
        while(t<qu[i].t) {
            t++;        ///最初的t=0,先增
            if(l<=op[t].x&&op[t].x<=r) {
                if(!--cnt[col[op[t].x]]) ans--;
                if(!cnt[op[t].now]++) ans++;
            }
            col[op[t].x]=op[t].now;
        }
        while(t>qu[i].t) {
            if(l<=op[t].x&&op[t].x<=r) {
                if(!--cnt[col[op[t].x]]) ans--;
                if(!cnt[op[t].lst]++) ans++;
            }
            col[op[t].x]=op[t].lst;
            t--;
        }
        while(r<qu[i].r) if(!cnt[col[++r]]++) ans++;
        while(l>qu[i].l) if(!cnt[col[--l]]++) ans++;
        while(r>qu[i].r) if(!--cnt[col[r--]]) ans--;
        while(l<qu[i].l) if(!--cnt[col[l++]]) ans--;
        res[qu[i].pos]=ans;
    }
    for(int i=1;i<=qu_num;i++)
        write(res[i]),pn;
    return 0;
}

  

posted @ 2019-07-17 16:23  wuliking  阅读(267)  评论(0编辑  收藏  举报