• P4396 [AHOI2013]作业 题解(分块+莫队)


    题目链接

    题目大意

    所有操作均为查询操作

    \(a[l],a[l+1]...a[r]\)中有多少个数在\([a,b]\)

    以及有多少个不同的数在\([a,b]\)

    题目思路

    全为查询考虑莫队

    莫队的修改为\(O(n\sqrt{m})\) 查询为\(O(m)\)

    而分块的修改一次\(O(1)\) 查询一次为\(O(\sqrt n)\)

    正好互补,最后的复杂度为\(O(m\sqrt n+n\sqrt m)\)

    实在太妙了

    代码

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    typedef unsigned long long ull;
    //typedef pair<int,int> pii;
    #define fi first
    #define se second
    #define debug printf("aaaaaaaaaaa\n");
    const int maxn=1e5+5,inf=0x3f3f3f3f,mod=1e9+7;
    const ll INF=0x3f3f3f3f3f3f3f3f;
    int n,m,k,block;
    int a[maxn];
    int num[maxn],ans[maxn][2],sum[maxn][2];
    struct node{
        int l,L,r,R,id;
    }q[maxn];
    bool cmp(node a,node b){
        return (a.r/block)==(b.r/block)?a.l<b.l:a.r<b.r;
    }
    void add(int x){
        num[x]++;
        if(num[x]==1){
            sum[x/block][0]++;
        }
        sum[x/block][1]++;
    }
    void del(int x){
        num[x]--;
        if(num[x]==0){
            sum[x/block][0]--;
        }
        sum[x/block][1]--;
    }
    int get(int r,int id){
        int x=r/block-1,ans=0;
        for(int i=0;i<=x;i++){
            ans+=sum[i][id];
        }
        for(int i=r/block*block;i<=r;i++){
            if(id==0){
                if(num[i]){
                    ans++;
                }
            }else{
                ans+=num[i];
            }
        }
        return ans;
    }
    int main(){
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++){
            scanf("%d",&a[i]);
        }
        block=sqrt(n);
        for(int i=1;i<=m;i++){
            scanf("%d%d%d%d",&q[i].l,&q[i].r,&q[i].L,&q[i].R);
            q[i].id=i;
        }
        sort(q+1,q+1+m,cmp);
        int l=1,r=1;
        add(a[1]);
        for(int i=1;i<=m;i++){
            while(l<q[i].l) del(a[l++]);
            while(l>q[i].l) add(a[--l]);
            while(r<q[i].r) add(a[++r]);
            while(r>q[i].r) del(a[r--]);
            ans[q[i].id][0]=get(q[i].R,0)-get(q[i].L-1,0);
            ans[q[i].id][1]=get(q[i].R,1)-get(q[i].L-1,1);
        }
        for(int i=1;i<=m;i++){
            printf("%d %d\n",ans[i][1],ans[i][0]);
        }
        return 0;
    }
    
    
    不摆烂了,写题
  • 相关阅读:
    Codeforces #533 div2 做题记录
    算法竞赛模板 打印素数表
    算法竞赛模板 计算组合数
    Educational Codeforces Round 34 (Rated for Div. 2)
    ACM感悟 -----sdust
    Codeforces Round #450 (Div. 2)
    EOJ Monthly 2017.12
    Wannafly挑战赛5
    二分图匹配
    今日颓废
  • 原文地址:https://www.cnblogs.com/hunxuewangzi/p/15037190.html
Copyright © 2020-2023  润新知