[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!

posted @ 2018-12-24 20:38  PaperCloud  阅读(139)  评论(0编辑  收藏  举报