[bzoj 2120]数颜色
传送门
Description
墨墨购买了一套N支彩色画笔(其中有些颜色可能相同),摆成一排,你需要回答墨墨的提问。墨墨会像你发布如下指令: 1、 Q L R代表询问你从第L支画笔到第R支画笔中共有几种不同颜色的画笔。 2、 R P Col 把第P支画笔替换为颜色Col。为了满足墨墨的要求,你知道你需要干什么了吗?
Solution
这是带修改的莫队
排序方式:按照
pos[l]
为第一关键字,pos[r]
为第二关键字,时间为第三关键字修改可以看作是一次插入和一次删除
而撤销修改同样也是一次修改和一次删除
设T是一块的长度
- 修改操作的维护,或者说是时间轴的移动,复杂度是\(O(\frac{n^3}{T^2})\)的
- 很显然,l,r的移动,复杂度是\(O(\frac{n^2}{T})+O(nT)\)
当\(T=n^{\frac{2}{3}}\)时,复杂度最优,为\(O(n^{\frac{3}{5}})\).
不过,如果你不心疼你的空间,也是可以分块做的
要对每个 块对 都处理出答案
Code
#include<bits/stdc++.h>
#define ll long long
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
return x*f;
}
#define MN 50005
int N,M,T,a[MN],pos[MN],totq,totu;
struct QUE{int l,r,t,id,ans;}q[MN];
struct UPD{int fr,to,x;}u[MN];
int ans;
inline bool cmp(const QUE&o,const QUE&oo)
{return (pos[o.l]^pos[oo.l])?(pos[o.l]<pos[oo.l]):((pos[o.r]^pos[oo.r])?(pos[o.r]<pos[oo.r]):(o.t<oo.t));}
int num[1000005];
inline bool cmp2(const QUE&o,const QUE&oo){return o.id<oo.id;}
int main()
{
N=read();M=read();
register int i,x;
register char ch[10];T=1357;
for(i=1;i<=N;++i) a[i]=read(),pos[i]=(i-1)/T+1;
for(i=1;i<=M;++i)
{
scanf("%s",ch+1);
if(ch[1]=='Q')
{
q[++totq].l=read(),q[totq].r=read();
q[totq].id=totq;q[totq].t=totu;
}
else
{
u[++totu].x=read(),u[totu].to=read();
u[totu].fr=a[u[totu].x];a[u[totu].x]=u[totu].to;
}
}
for(i=totu;i;--i) a[u[i].x]=u[i].fr;
std::sort(q+1,q+totq+1,cmp);
register int j=0,l=1,r=0,ans=0;
for(i=1;i<=totq;++i)
{
for(;l>q[i].l;--l) ans+=!(num[a[l-1]]++);
for(;l<q[i].l;++l) ans-=!(--num[a[l]]);
for(;r<q[i].r;++r) ans+=!(num[a[r+1]]++);
for(;r>q[i].r;--r) ans-=!(--num[a[r]]);
for(;j<q[i].t;++j)
{
a[u[j+1].x]=u[j+1].to;
if(u[j+1].x<=q[i].r&&u[j+1].x>=q[i].l)
ans-=!(--num[u[j+1].fr]),ans+=!(num[u[j+1].to]++);
}
for(;j>q[i].t;--j)
{
a[u[j].x]=u[j].fr;
if(u[j].x<=q[i].r&&u[j].x>=q[i].l)
ans+=!(num[u[j].fr]++),ans-=!(--num[u[j].to]);
}
q[i].ans=ans;
}
std::sort(q+1,q+totq+1,cmp2);
for(i=1;i<=totq;++i) printf("%d\n",q[i].ans);
}
Blog来自PaperCloud,未经允许,请勿转载,TKS!
致虚极,守静笃,万物并作,吾以观其复