zoukankan      html  css  js  c++  java
  • CDQ分治

    我tm终于把三维偏序调对了

    CDQ分治是一种进行计算时的降维手段,简单说大家都知道在进行一维偏序时我们只需要排序,二维偏序则可以用树状数组+排序,这之中树状数组就是一个降维手段,它将二维偏序降维,然后就可以用一维偏序做了。CDQ和树套树也是同理,以听说CDQ可以解决m维偏序,时间复杂度nlog(m-1)n

    CDQ的思想主要是分治,然后计算前半部分对后半部分产生的影响所以说常规分治其实是恰好前半部分对后半部分没影响的CDQ??

    下面就是代码(三维偏序),思路是排序一维,CDQ一维,CDQ中用树状数组统计第三维

    重点:

    1.CDQ分治中树状数组一定不要memset!把树状数组的加法减回去就好了;

    2.排序后再记一次rank可以大幅降低编程难度;

    3.对于重复数据我们可以记录每个数据排序最靠后的一个,它的答案就是所有这个数据的答案(想想为什么)

    代码略丑

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<cstdlib>
    #include<algorithm>
    #define lowbit(x) (x&(-x))
    using namespace std;
    struct data
    {
        int x,y,z,num,num2;
        bool operator < (const data &a) const
        {
            if(x==a.x)
            {
                if(y==a.y) return z<a.z;
                return y<a.y;
            }
            return x<a.x;
        }
        bool operator != (const data &a) const
        {
            return ((x!=a.x)||(y!=a.y)||(z!=a.z));
        }
    }P[100010];
    bool cmp(data a,data b)
    {
        if(a.y==b.y) 
        {
            return a.num2<b.num2;
        }
        return a.y<b.y;
    }
    int n,k;
    int c[450010],ans[100010],ans2[100010];
    int to[100010];
    void add(int p,int x){for(int i=p;i<=400010;i+=lowbit(i))c[i]+=x;}
    int query(int p){int tmp=0;for(int i=p;i>=1;i-=lowbit(i))tmp+=c[i];return tmp;}
    void cdq(int l,int r)
    {
        if(l==r) return;
        int mid=(l+r)/2;
        data mi=P[mid];
        cdq(l,mid);cdq(mid+1,r);
        sort(P+l,P+r+1,cmp);
        for(int i=l;i<=r;i++)
        {
            if(P[i].num2<=mi.num2) 
            {
                add(P[i].z,1);
            }
            else 
            {
                ans[P[i].num]+=query(P[i].z);
            }
        }
        for(int i=l;i<=r;i++)
        {
            if(P[i].num2<=mi.num2) add(P[i].z,-1);
        }
        return;
    }
    int main()
    {
        scanf("%d%d",&n,&k);
        for(int i=1;i<=n;i++)
        {
            P[i].num=i;
            scanf("%d%d%d",&P[i].x,&P[i].y,&P[i].z);
        } 
        sort(P+1,P+n+1);
        P[n+1].x=-1;
        int flag=1;
        for(int i=1;i<=n;i++)
        {
            P[i].num2=i;
            if(P[i]!=P[i+1])
            {
                for(int j=flag;j<=i;j++) to[P[j].num]=P[i].num;
                flag=i+1;    
            } 
        }
        cdq(1,n);
        for(int i=1;i<=n;i++)
        {
            ans2[ans[to[i]]]++;
        }
        for(int i=0;i<n;i++)
        {
            printf("%d
    ",ans2[i]);
        }
    }
    CDQ三维偏序
  • 相关阅读:
    CompletableFuture java 8新增加异步处理
    Java并发编程:CountDownLatch、CyclicBarrier和 Semaphore , Condition
    怎么让一个不定宽高的div垂直水平居中?
    数组对象方法排序
    Webpack ERROR in Path must be a string. Received undefined
    es6 babel转码器安装配置及常见命令
    使用淘宝镜像cnpm安装Vue.js
    JS中的call()和apply()方法
    placeholder颜色更改
    typeof与js数据类型
  • 原文地址:https://www.cnblogs.com/wjxgy/p/8037722.html
Copyright © 2011-2022 走看看