P1903 数颜色

P1903 数颜色

Description

对于每个位置,有颜色。有两个操作,修改当前位置颜色、查询 \([L,R]\) 区间内颜色种类数。

Solution

我们考虑带修莫队。
由于询问都是按照莫队排序,所以未必按照时间轴排序,我们考虑记下当前询问的最新修改时间戳,而后我们对于这样一个时间戳进行还原。

Code

#include<bits/stdc++.h>
using namespace std;

const int N=1e6+8;

int n,m,len;
int col[N];
int belongs[N];
char op;
int cntq,cntp;
int res[N];
int ans;
int cnt[N];
int l,r,t;

struct node1{
  int l,r,t,id;
  friend bool operator < (node1 a,node1 b){
    return belongs[a.l]==belongs[b.l]?belongs[a.r]==belongs[b.r]?a.t<b.t:belongs[a.r]<belongs[b.r]:belongs[a.l]<belongs[b.l];
  }
}Q[N];

struct node2{
  int pos,col;
}P[N];

void add(int x){if(!cnt[x])ans++;cnt[x]++;}

void del(int x){cnt[x]--;if(!cnt[x])ans--;}

void upd(node1 q,node2 &p){
  if(q.l<=p.pos&&p.pos<=q.r) del(col[p.pos]),add(p.col);
  swap(col[p.pos],p.col);
}

void solve(node1 q){
  while(l>q.l) add(col[--l]);
  while(r<q.r) add(col[++r]);
	while(l<q.l) del(col[l++]);
	while(r>q.r) del(col[r--]);
	while(t<q.t) upd(q,P[++t]);
	while(t>q.t) upd(q,P[t--]);
	res[q.id]=ans;
}

int main(){
  scanf("%d%d",&n,&m);
  len=pow(n,0.666);
  for(int i=1;i<=n;i++) scanf("%d",&col[i]),belongs[i]=(i-1)/len+1;
  for(int i=1;i<=m;i++){
    scanf("%s",&op);
    if(op=='Q') cntq++,scanf("%d%d",&Q[cntq].l,&Q[cntq].r),Q[cntq].t=cntp,Q[cntq].id=cntq;
    else cntp++,scanf("%d%d",&P[cntp].pos,&P[cntp].col);
  }
  sort(Q+1,Q+1+cntq);
  l=1,r=0,t=0;
  for(int i=1;i<=cntq;i++) solve(Q[i]);
  for(int i=1;i<=cntq;i++) printf("%d\n",res[i]);
  return 0;
}
posted @ 2023-08-13 08:26  Zimo_666  阅读(5)  评论(0编辑  收藏  举报