• bzoj5016 一个简单的询问


    这种不可直接做的问题

    数据范围又很小

    考虑莫队

    但是,l1,l2,r1,r2四维?

    考虑把询问二维差分!

    f(a,b)表示,询问[1,a],[1, b]的答案

    所以,ans(l1,r1,l2,y2)=f(r1,r2)-f(l1-1,r2)-f(r1,l2-1)+f(l1-1,l2-1)

    正确性的话,考虑每一个种类k被统计的情况,c*d=(a+b)*(c+d)-a*(c+d)-c*(a+b)+a*b

    需要离散化

    数组开4倍

    #include<bits/stdc++.h>
    #define il inline
    #define reg register int
    #define numb (ch^'0')
    using namespace std;
    typedef long long ll;
    il void rd(int &x){
        char ch;bool fl=false;
        while(!isdigit(ch=getchar()))(ch=='-')&&(fl=true);
        for(x=numb;isdigit(ch=getchar());x=x*10+numb);
        (fl==true)&&(x=-x);
    }
    namespace Miracle{
    const int N=50000+5;
    int n,m;
    int a[N];
    int blo[N];
    int b[N];
    ll ans[N];
    struct que{
        int l,r;
        int c,id;
        que(){}
        que(int ll,int rr,int cc,int dd){
            if(ll>rr) swap(ll,rr);
            l=ll;r=rr;c=cc;id=dd;
        }
        bool friend operator <(que a,que b){
            if(blo[a.l]==blo[b.l]){
                if(blo[a.l]&1) return a.r<b.r;
                return a.r>b.r;
            }
            return blo[a.l]<blo[b.l];
        }
    }q[4*N];
    int tot;
    int buc[2][N];
    ll now;
    int l,r;
    void dele(int d,int c){
        now-=buc[d^1][c];
        buc[d][c]--;
    }
    void add(int d,int c){
        now+=buc[d^1][c];
        buc[d][c]++;
    }
    void modui(){
        l=0;r=0;now=0;
        for(reg i=1;i<=tot;++i){
            while(l<q[i].l) ++l,add(0,a[l]);
            while(l>q[i].l) dele(0,a[l]),--l;
            while(r<q[i].r) ++r,add(1,a[r]);
            while(r>q[i].r) dele(1,a[r]),--r;
            ans[q[i].id]+=(ll)now*q[i].c;
        }
    }
    int main(){
        rd(n);
        for(reg i=1;i<=n;++i){
            rd(a[i]);
            blo[i]=(i-1)/223+1;
            b[i]=a[i];
        }
        sort(b+1,b+n+1);
        int cnt=unique(b+1,b+n+1)-b-1;
        for(reg i=1;i<=n;++i){
            a[i]=lower_bound(b+1,b+cnt+1,a[i])-b;
            //cout<<" a[i] "<<a[i]<<endl;
        }
        rd(m);
        int l1,l2,r1,r2;
        for(reg i=1;i<=m;++i){
            rd(l1);rd(r1);rd(l2);rd(r2);
            if(l1>1&&l2>1) q[++tot]=que(l1-1,l2-1,1,i);
            if(l1>1) q[++tot]=que(l1-1,r2,-1,i);
            if(l2>1) q[++tot]=que(r1,l2-1,-1,i);
            q[++tot]=que(r1,r2,1,i);
        }
        sort(q+1,q+tot+1);
        modui();
        for(reg i=1;i<=m;++i){
            printf("%lld
    ",ans[i]);
        }
        return 0;
    }
    
    }
    signed main(){
        Miracle::main();
        return 0;
    }
    
    /*
       Author: *Miracle*
       Date: 2019/1/27 22:24:01
    */

    询问的二维拆分有点意思!

    以前并没有遇到这种问题(最多就是一维差分)

    之前莫队都是(l,r)这种

    如果可以前缀差分的话,那么多个(li,ri)都是可以的

    本质就是容斥,或者高维差分

  • 相关阅读:
    spring profile 多环境配置管理
    搭建docker私服仓库
    ubuntu安装mysql添加密码
    yum源安装docker
    keep + haproxy 运行原理
    gitlab汉化
    什么是DevOps?
    Kafka高并发原理概述
    k8s + flannel 内网不能互通问题排查
    Flannel跨主机互联概述及容器网络拓扑图
  • 原文地址:https://www.cnblogs.com/Miracevin/p/10331033.html
Copyright © 2020-2023  润新知