zoukankan      html  css  js  c++  java
  • 离线算法入门——CDQ分治

    离线算法入门——CDQ分治

    1 简介

    CDQ 分治只能算作一种方法而非一种通用的算法,对于一段操作序列,我们从中间分开,先处理左边,再处理右边,最后加上左边对右边的影响。归并排序实际上就是一个 CDQ 分治。

    2 例题

    2.1 三维偏序

    链接

    我们首先按照第一维从大到小排序。这样接下来我们只需要考虑第二第三层。考虑 CDQ 分治,如何统计左边对右边的贡献呢?我们可以把两边都按照第二维排序,然后用双指针统计答案。

    需要注意的是,如果两个元素第一维相同,第二维不同,我们需要让左边的第二维严格小于右边。否则这个答案就可能统计不上,因为相同的元素如果划分到一个区域里可能统计不了答案,我们需要提前去重。

    代码:

    #include<bits/stdc++.h>
    #define dd double
    #define ld long double
    #define ll long long
    #define uint unsigned int
    #define ull unsigned long long
    #define N 200010
    #define M number
    using namespace std;
    
    const int INF=0x3f3f3f3f;
    
    template<typename T> inline void read(T &x) {
        x=0; int f=1;
        char c=getchar();
        for(;!isdigit(c);c=getchar()) if(c == '-') f=-f;
        for(;isdigit(c);c=getchar()) x=x*10+c-'0';
        x*=f;
    }
    
    int n,k,f[N],tong[N];
    
    struct BIT{
        int p[N];
        inline int lowbit(int x){return x&(-x);}
        inline void add(int x,int val){for(int i=x;i<=k;i+=lowbit(i))p[i]+=val;}
        inline int ask_sum(int x){int ans=0;for(int i=x;i>=1;i-=lowbit(i)) ans+=p[i];return ans;}
    };
    BIT bit;
    
    struct flower{
        int a,b,c,cnt,ans;
        inline bool operator == (const flower &b) const{
            return (a==b.a)&&(this->b==b.b)&&(c==b.c);
        }
    };
    flower fl[N];
    
    inline bool cmp1(flower a,flower b){
        if(a.a!=b.a) return a.a<b.a;
        else if(a.b!=b.b) return a.b<b.b;
        else return a.c<b.c;
    }
    
    inline bool cmp2(flower a,flower b){
        if(a.b!=b.b) return a.b<b.b;
        else return a.c<b.c;
    }
    
    inline void cdq(int l,int r){
        if(l==r) return;
        int mid=(l+r)>>1;
        cdq(l,mid);cdq(mid+1,r);
        sort(fl+l,fl+mid+1,cmp2);
        sort(fl+mid+1,fl+r+1,cmp2);
        int i=l,j=mid+1;
        for(;j<=r;j++){
            while(fl[i].b<=fl[j].b&&i<=mid){
                bit.add(fl[i].c,fl[i].cnt);i++;
            }
            fl[j].ans+=bit.ask_sum(fl[j].c);
        }
        for(int w=l;w<i;w++) bit.add(fl[w].c,-fl[w].cnt);
    }
    
    int main(){
        // freopen("my.in","r",stdin);
        // freopen("my.out","w",stdout);
        read(n);read(k);
        for(int i=1;i<=n;i++){
            read(fl[i].a);read(fl[i].b);read(fl[i].c);
        }
        sort(fl+1,fl+n+1,cmp1);
        int tail=0;fl[++tail]=fl[1];fl[tail].cnt=1;
        for(int i=2;i<=n;i++){
            if(fl[i]==fl[i-1]){
                fl[tail].cnt++;
            }
            else fl[++tail]=fl[i],fl[tail].cnt=1;
        }
        cdq(1,tail);
        for(int i=1;i<=tail;i++) tong[fl[i].ans+fl[i].cnt-1]+=fl[i].cnt;
        for(int i=0;i<=n-1;i++) printf("%d
    ",tong[i]);
        return 0;
    }
    
  • 相关阅读:
    protobuf 一个c++示例
    protobuf 之 MessageLite 接口摘录
    export setenv
    Centos java 安装
    C++中防止STL中迭代器失效——map/set等关联容器——vector/list/deque等序列容器—如何防止迭代器失效—即erase()的使用
    centos 安装tkdiff
    Redis 入门指南
    VB.NET+三层 机房收费系统之组合查询
    Android studio 插件之 GsonFormat (自己主动生成javabean)
    ubuntu14.04恢复系统默认中文字体
  • 原文地址:https://www.cnblogs.com/TianMeng-hyl/p/14978786.html
Copyright © 2011-2022 走看看