2120: 数颜色
Time Limit: 6 Sec Memory Limit: 259 MBSubmit: 5428 Solved: 2165
[Submit][Status][Discuss]
Description
墨墨购买了一套N支彩色画笔(其中有些颜色可能相同),摆成一排,你需要回答墨墨的提问。墨墨会像你发布如下指令: 1、 Q L R代表询问你从第L支画笔到第R支画笔中共有几种不同颜色的画笔。 2、 R P Col 把第P支画笔替换为颜色Col。为了满足墨墨的要求,你知道你需要干什么了吗?
Input
第1行两个整数N,M,分别代表初始画笔的数量以及墨墨会做的事情的个数。第2行N个整数,分别代表初始画笔排中第i支画笔的颜色。第3行到第2+M行,每行分别代表墨墨会做的一件事情,格式见题干部分。
Output
对于每一个Query的询问,你需要在对应的行中给出一个数字,代表第L支画笔到第R支画笔中共有几种不同颜色的画笔。
Sample Input
6 5
1 2 3 4 5 5
Q 1 4
Q 2 6
R 1 2
Q 1 4
Q 2 6
1 2 3 4 5 5
Q 1 4
Q 2 6
R 1 2
Q 1 4
Q 2 6
Sample Output
4
4
3
4
4
3
4
HINT
对于100%的数据,N≤10000,M≤10000,修改操作不多于1000次,所有的输入数据中出现的所有整数均大于等于1且不超过10^6。
这个题 解法多多
最开始想的是树状数组套主席树
还有PoPoQQQ大爷暴力水过
当然也有带修改莫队
#include<cmath>
#include<ctime>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<complex>
#include<iostream>
#include<algorithm>
#include<iomanip>
#include<vector>
#include<string>
#include<bitset>
#include<queue>
#include<set>
#include<map>
using namespace std;
typedef long long ll;
inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch<48||ch>57){if(ch=='-')f=-1;ch=getchar();}
while(ch<=57&&ch>=48){x=(x<<1)+(x<<3)+ch-48;ch=getchar();}
return x*f;
}
void print(int x)
{if(x<0)putchar('-'),x=-x;if(x>=10)print(x/10);putchar(x%10+48);}
const int N=10100,M=1000100;
int bel[N],n,Q,sz,cnt;
struct question{int l,r,time,id;}q[N];
inline bool cmp( question x, question y)
{return bel[x.l]==bel[y.l]?x.r<y.r:bel[x.l]<bel[y.l];}
struct change_clr{int pos,clr,pre;}w[N];
int clr[N],last[N],ans[N],num[M],res;
bool vis[N];
inline void cal(int x)
{
if(vis[x])if(!(--num[clr[x]]))res--;
if(!vis[x])if((++num[clr[x]])==1)res++;
vis[x]^=1;
}
inline void modify(int k,int val)
{if(vis[k]){cal(k);clr[k]=val;cal(k);}else clr[k]=val;}
void solve()
{
register int l=1,r=1,i,j;cal(1);
for(i=1;i<=sz;++i)
{
for(j=q[i-1].time+1;j<=q[i].time;++j)modify(w[j].pos,w[j].clr);
for(j=q[i-1].time;j>q[i].time;j--)modify(w[j].pos,w[j].pre);
while(r<q[i].r)cal(++r);
while(r>q[i].r)cal(r--);
while(l>q[i].l)cal(--l);
while(l<q[i].l)cal(l++);
ans[q[i].id]=res;
}
}
int main()
{
n=read();Q=read();
register int i,x,y,block;char ch[10];
for(i=1;i<=n;++i)clr[i]=read(),last[i]=clr[i];
for(i=1;i<=Q;++i)
{
scanf("%s",ch);x=read();y=read();
if(ch[0]=='R'){w[++cnt].pos=x;w[cnt].clr=y;w[cnt].pre=last[x];last[x]=y;}
else {q[++sz].l=x;q[sz].r=y;q[sz].id=sz;q[sz].time=cnt;}
}
block=sqrt(n);
for(i=1;i<=n;++i)bel[i]=(i-1)/block+1;
sort(q+1,q+sz+1,cmp);
solve();
for(i=1;i<=sz;++i)print(ans[i]),puts("");
return 0;
}
/*
6 5
1 2 3 4 5 5
Q 1 4
Q 2 6
R 1 2
Q 1 4
Q 2 6
4
4
3
4
*/