zoukankan      html  css  js  c++  java
  • 【题解】[洛谷 P4396 / bzoj 3236] 作业【莫队 分块 根号平衡】

    题目链接

    题目链接

    题意

    给定序列 (a),多次询问:

    • (a[l..r]) 有多少数在 ([a..b]) 中;
    • (a[l..r]) 有多少数在 ([a..b]) 中(去重)。

    (n,mleq 10^5)

    题解

    莫队显然。每次移动指针时要单点修改((O(nsqrt n)) 次),查询时查询区间和((O(n)) 次)。用分块实现 (O(1)) 修改、(O(sqrt n)) 查询,复杂度为 (O(nsqrt n))

    #include<bits/stdc++.h>
    using namespace std;
    
    const int BUF_LEN=1<<19;
    struct FastIO{
        char bufi[BUF_LEN+10],*PTi=bufi+BUF_LEN,*PTENDi=bufi+BUF_LEN;
        inline char gc(){
            (PTi==PTENDi)&&(bufi[fread(bufi,1,BUF_LEN,stdin)]=0,PTi=bufi);
            return *(PTi++);
        }
        char bufo[BUF_LEN+10],*PTo=bufo,*PTENDo=bufo+BUF_LEN;
        inline void pc(char c){
            (PTo==PTENDo)&&(fwrite(bufo,1,BUF_LEN,stdout),PTo=bufo);
            *(PTo++)=c;
        }
        void flush(){
            fwrite(bufo,1,PTo-bufo,stdout);
            PTo=bufo;
        }
        ~FastIO(){
            flush();
        }
    
        template<class T>inline void getint(T &x=0){
            char c=gc();
            int f=1;x=0;
            while(c<'0'||c>'9'){
                if(c=='-')f=-1;
                c=gc();
            }
            while(c>='0'&&c<='9'){
                x=x*10+c-'0'; 
                c=gc();
            }
            if(f==-1)x=-x;
        }
        operator int(){
            int v;getint(v);return v;
        }
        operator long long(){
            long long v;getint(v);return v;
        }
        template<class T>inline void putint(T x=0,char sep=' '){
            char tmp[20],len=0;
            if(x<0)pc('-'),x=-x;
            if(x==0){ pc('0');pc(sep);return; }
            while(x)tmp[len++]=x%10,x/=10;
            for(int i=len-1;~i;--i)pc(tmp[i]|'0');
            pc(sep);
        }
    }io;
    
    const int N=1e5+10,M=1e6+10,Q=1010;
    struct Block_div{
        int blk;
        int s[Q],a[N];
        void modify(int x,int y){ s[x/blk]+=y,a[x]+=y; }
        int query(int r){
            int ans=0;
            int i=blk-1;
            for(int j=0;i<=r;i+=blk,j++)ans+=s[j];
            for(i-=blk-1;i<=r;i++)ans+=a[i];
            return ans;
        }
    };
    Block_div s,uni;
    
    int n,m;
    int a[N];
    int blk,bl[N];
    struct Query{
        int l,r,a,b,num;
    }q[M];
    bool cmp(const Query &a,const Query &b){
        return bl[a.l]^bl[b.l]?bl[a.l]<bl[b.l]:bl[a.l]&1?a.r<b.r:a.r>b.r;
    }
    int ans1[M],ans2[M];
    
    int main(){
        n=io,m=io;
        blk=max(n/sqrt(m*0.8),1.0);
        s.blk=uni.blk=sqrt(n);
        for(int i=1;i<=n;i++)a[i]=io;
    
        for(int i=1;i<=n;i++)bl[i]=i/blk;
        for(int i=0;i<m;i++)q[i].l=io,q[i].r=io,q[i].a=io,q[i].b=io,q[i].num=i;
        sort(q,q+m,cmp);
        
        int l=2,r=1;
        for(int i=0;i<m;i++){
            while(l<q[i].l){
                s.modify(a[l],-1);
                if(!s.a[a[l]])uni.modify(a[l],-1);
                ++l;
            }
            while(r>q[i].r){
                s.modify(a[r],-1);
                if(!s.a[a[r]])uni.modify(a[r],-1);
                --r;
            }
            while(l>q[i].l){
                --l;
                if(!s.a[a[l]])uni.modify(a[l],1);
                s.modify(a[l],1);
            }
            while(r<q[i].r){
                ++r;
                if(!s.a[a[r]])uni.modify(a[r],1);
                s.modify(a[r],1);
            }
            ans1[q[i].num]=s.query(q[i].b)-s.query(q[i].a-1);
            ans2[q[i].num]=uni.query(q[i].b)-uni.query(q[i].a-1);
        }
        for(int i=0;i<m;i++)io.putint(ans1[i],' '),io.putint(ans2[i],'
    ');
    }
    
    
  • 相关阅读:
    python threading acquire release
    .net支付宝调试
    C#获取微信openid
    KindeEditor图片上传插件用法
    .net Repeater内部的按钮事件代码demo(Repeater内button的删除事件)
    .net 执行页面跳转弹窗提示,刷新代码
    .net验证控件
    上传图片
    数据库写入时间
    数据库读取
  • 原文地址:https://www.cnblogs.com/wallbreaker5th/p/14251799.html
Copyright © 2011-2022 走看看