洛谷P1903 [国家集训队]数颜色 / 维护队列

题意:有两种操作:

        1、 Q L R代表询问你从第L支画笔到第R支画笔中共有几种不同颜色的画笔。

        2、 R P Col 把第P支画笔替换为颜色Col。

        对每个1操作 输出答案;

    带修莫队 模板题 (加多个T指针) 多注意细节

#include<bits/stdc++.h>
#define LL long long
#define ULL unsigned long long
#define rep(i,j,k) for(int i=j;i<=k;i++)
#define dep(i,j,k) for(int i=k;i>=j;i--)
#define INF 0x3f3f3f3f
#define mem(i,j) memset(i,0,sizeof(i))
#define make(i,j) make_pair(i,j)
using namespace std;
int a[500005],pos[500005],num[1000005],ans[500005],tmp,l=1,r=0;
int now[500005];
struct noqu {
    int l,r,id,t;
}q[500005];
struct noch {
    int x,old,ne;
}c[500005];
bool cmp(noqu a,noqu b) {
    if(pos[a.l]==pos[b.l]) {
        if(pos[a.r]==pos[b.r]) {
            return a.t<b.t;
        }
        return pos[a.r]<pos[b.r];
    }
    return pos[a.l]<pos[b.l];
}
void rever(int x,int d) {
    num[x]+=d;
    if(d>0&&num[x]==1) tmp++;
    else if(d<0 && num[x]==0) tmp--;
}
void init(int x,int ne) {
    if(l<=x && x<=r) {
        rever(ne,1); rever(a[x],-1);
    }
    a[x]=ne;
}
char s[5]; int x,y;
int main() {
    int n,m;
    scanf("%d %d",&n,&m); int N=floor(pow(n,0.666666));
    rep(i,1,n) {
        scanf("%d",&a[i]); now[i]=a[i];  pos[i]=(i-1)/N;
    }
    int head=0,tail=0;
    rep(i,1,m) {
        scanf("%s",s); scanf("%d%d",&x,&y);
        if(s[0]=='Q') {
            q[++head]=(noqu){x,y,head,tail};
        }
        else {
            c[++tail]=(noch){x,now[x],y};
            now[x]=y;
        }
    }
    sort(q+1,q+1+head,cmp); int T=0;
    rep(i,1,head) {
        while(T<q[i].t) { ++T; init(c[T].x,c[T].ne); }
        while(T>q[i].t) {init(c[T].x,c[T].old); --T;}
        while(l<q[i].l) rever(a[l++],-1);
        while(l>q[i].l) rever(a[--l],1);
        while(r<q[i].r) rever(a[++r],1);
        while(r>q[i].r) rever(a[r--],-1);
        ans[q[i].id]=tmp;
    }
    rep(i,1,head) printf("%d\n",ans[i]);
    return 0;
}
View Code

猜你喜欢

转载自www.cnblogs.com/Willems/p/10887340.html
今日推荐