• [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
    ",q[i].ans);
    }
    


    Blog来自PaperCloud,未经允许,请勿转载,TKS!

  • 相关阅读:
    C# 调用Java Webservice 加入SoapHeader 验证信息
    SqlServer查找表中多余的重复记录
    INI文件的读写
    Sql触发器脚本
    Sql遍历更新脚本
    CAS 单点登录,通过ticket 获取登录用户
    模块 | 验证格式
    aja如何解决跨域请求?
    说说各个浏览器box模型
    Vue 双向数据绑定原理分析
  • 原文地址:https://www.cnblogs.com/PaperCloud/p/10170847.html
Copyright © 2020-2023  润新知