• BZOJ 2120: 数颜色


    Description

    给你一个序列,询问 ([L,R]) 区间中颜色种数,支持修改操作,不强制在线. (n,mleqslant 10^4)

    Sol

    三维莫队. QAQ.

    简单的说一下吧...

    三维莫队就是维护三元组 ((L,R,T)) 的答案,表示 ([L,R]) 区间在进行了 (T) 次修改后的答案.

    然后就可以处理 (Lpm 1,Rpm 1,Tpm 1) 的答案了.

    关于三维莫队:

    我们需要对 (L,R) 分块,像处理二维莫队一样按 (L,R,T) 的顺序排序,移动 (L,R) 直接统计颜色个数移动就可以.

    对于 (T) 的移动,它表示的其实是一个前缀,那么对于 (T) 的移动就可以删去再把新元素加上贡献就可以,使它直接和原来的元素交换,这样不管扩大还是缩小都是适用的.

    关于复杂度:

    因为需要枚举前两维的块,最后一维直接暴力,那么设块大小为 (B) ,则有复杂度

    (O((frac{n}{B})^2*n+mB))

    (O(frac{n^3}{B^2}+mB))

    求导.

    (m+n^3*(-2)*B^{-3}=0)

    (B^3=frac{n^3}{m})

    因为 (n,m) 同阶,

    (B^3=n^2)

    (B=n^{frac{2}{3}})

    所以复杂度为 (O(n^{frac{5}{3}})) .

    PS1:从这篇博客开始写简述题意

    PS2:复杂度证明问的TA爷 QAQ.

    PS3:三维莫队其实没用QAQ,跑不了 (10^5) 也就跑跑 (10^4)

    Code

    /**************************************************************
        Problem: 2120
        User: BeiYu
        Language: C++
        Result: Accepted
        Time:2232 ms
        Memory:5720 kb
    ****************************************************************/
     
    #include<cstdio>
    #include<cmath>
    #include<utility>
    #include<vector>
    #include<algorithm>
    #include<cstring>
    #include<iostream>
    using namespace std;
     
    const int N = 10005;
    const int M = 1000005;
    #define mpr(a,b) make_pair(a,b)
     
    int n,m,B,cp,cq;
    int a[N],c[M];
    int b1[N],b2[N];
    int L,R,T,ans;
    pair<int,int> s[N];
     
    struct Q{ int l,r,t,id; }p[N],q[N];
    bool operator < (const Q &a,const Q &b){
        if(b1[a.l]!=b1[b.l]) return b1[a.l]<b1[b.l];
        if(b2[a.r]!=b2[b.r]) return b2[a.r]<b2[b.r];
        return a.t<b.t;
    }
     
    inline int in(int x=0,char ch=getchar()){ while(ch>'9'||ch<'0') ch=getchar();
        while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();return x; }
     
    void Move(int x,int v){
        if(v==-1){ if((--c[a[x]])==0) ans--; }
        else{ if((++c[a[x]])==1) ans++; }
    }
    void Update(int x){
        if(L<=p[x].l&&p[x].l<=R) Move(p[x].l,-1);
        swap(p[x].r,a[p[x].l]);
        if(L<=p[x].l&&p[x].l<=R) Move(p[x].l,1);
    }
     
    int main(){
    //  freopen("in.in","r",stdin);
        n=in(),m=in();
        for(int i=1;i<=n;i++) a[i]=in();
        for(int i=1;i<=m;i++){
            char ch=getchar();while(ch>'Z'||ch<'A') ch=getchar();
            int u=in(),v=in();
            if(ch=='R') p[++cp]=(Q){ u,v,0,0 };
            else q[++cq]=(Q){ u,v,cp,i };
        }B=pow(n,5.0/3);
        for(int i=1;i<=n;i++) b1[i]=b2[i]=(i-1)/B+1;
        sort(q+1,q+cq+1);
        Move(1,1),L=R=1,T=0;
        for(int i=1;i<=cq;i++){
            while(R<q[i].r) Move(++R,+1);while(R>q[i].r) Move(R--,-1);
            while(L<q[i].l) Move(L++,-1);while(L>q[i].l) Move(--L,+1);
            while(T>q[i].t) Update(T--);while(T<q[i].t) Update(++T);
    //      cout<<L<<" "<<R<<" "<<T<<" "<<ans<<endl;
            s[i]=mpr(q[i].id,ans);
        }sort(s+1,s+cq+1);
        for(int i=1;i<=cq;i++) printf("%d
    ",s[i].second);
        return 0;
    }
    

      

  • 相关阅读:
    IOS开发银行系统的四舍五入的算法
    线程通信之初认识
    多线程同步机制练习之银行存钱
    解决线程安全问题方式三:loke锁
    使用同步机制解决单例模式中的懒汉式的线程安全问题
    (对于继承Thread类)线程安全问题解决方式二:同步静态方法
    (对于实现Runnable接口)线程安全问题解决方式二:同步方法
    (对于继承Thread类)线程安全问题解决方式一:同步代码块
    (对于实现Runnable接口)线程安全问题解决方式一:同步代码块
    三个窗口卖票(实现Runnable方式创建线程)之线程安全问题
  • 原文地址:https://www.cnblogs.com/beiyuoi/p/5894133.html
Copyright © 2020-2023  润新知