链接:https://www.lydsy.com/JudgeOnline/problem.php?id=2120
题意:多个区间询问,询问[l,r]中颜色的种类数。可以单点修改颜色。
分析:
一个裸的带修莫队
代码:
#include<stdio.h>
#include<algorithm>
#include<math.h>
using namespace std;
int n,m,b[10500],s[10500],now[10500],Time,l,r,ans,po[10500],sum[1050000];
struct node
{
int l,r,time,id;
}v[10500];
struct Change
{
int pos,now,pre;
}h[10500];
bool com1 (node aa,node bb)
{
return b[aa.l]==b[bb.l]?(b[aa.r]==b[bb.r]?aa.time<bb.time:aa.r<bb.r):(aa.l<bb.l);
}
void uppdate(int pos,int add)
{
sum[s[pos]]+=add;
if(sum[s[pos]]==0&&add<0)
ans--;
else
if(sum[s[pos]]==1&&add>0)
ans++;
}
void update(int x,int now)
{
if(l<=x&&r>=x)
{
uppdate(x,-1);
s[x]=now;
uppdate(x,1);
}
else
s[x]=now;
}
int main()
{
int i,j,tt,Size;
scanf("%d%d",&n,&m);
Size=pow(n,0.66666);
for(i=1;i<=n;i++)
{
scanf("%d",&s[i]);
now[i]=s[i];
b[i]=i/Size+1;
}
char cc;
int aa,bb,t;
Time=0;
tt=0;
for(i=1;i<=m;i++)
{
scanf(" %c %d%d",&cc,&aa,&bb);
if(cc=='Q'){v[++tt]=(node){aa,bb,Time,tt};}
else
if(cc=='R')
{
h[++Time]=(Change){aa,bb,now[aa]};
now[aa]=bb;
}
}
t=0;
l=1;
r=0;
sort(v+1,v+1+tt,com1);
for(i=1;i<=tt;i++)
{
while(t<v[i].time){
update(h[t+1].pos,h[t+1].now);
t++;
}
while(t>v[i].time){
update(h[t].pos,h[t].pre);
t--;
}
while(l<v[i].l){
uppdate(l,-1);
l++;
}
while(l>v[i].l){
uppdate(l-1,1);
l--;
}
while(r<v[i].r){
uppdate(r+1,1);
r++;
}
while(r>v[i].r){
uppdate(r,-1);
r--;
}
po[v[i].id]=ans;
}
for(i=1;i<=tt;i++)
printf("%d\n",po[i]);
}