• CDQ分治 三维偏序


    这应该是一道CDQ分治的入门题目

    我们知道,二维度的偏序问题直接通过,树状数组就可以实现了,但是三维如何实现呢?

    我记得以前了解过一个小故事,应该就是分治的。

    一个皇帝,想给部下分配任务,但是部下太多,他也无从下手于是他这个任务分给宰相,宰相也不怎么清楚,于是他又分给他的手下,这么一直分啊分啊,分到每一个人头顶上的时候

    每个人知道自己要干什么,于是他把它的信息交给他的上级,上级有了这些数据后,他处理了交给他的上级。。。这么一直交啊。。。国王最后成功的分配这些任务。

    CDQ分治也是一样,在这里,首先我们需要对X坐标进行排序,排序成功后,我们对区间进行分割,每次对区间进行二分,分成 [L - MID] [MID+1 - R] 

    我们分到底部的时候,实际上就是左右相等,于是只需要计算单个元素的效果,然后回到上一级,由于我们计算了两个区间的值,所以只需要计算 [MID+1 R] 对[L ,MID] 结果的影响即可

    放到这道题,我们把X排序,然后枚举区间,对于【L,MID】对【MID+1,R】区间的贡献来说,应该如何计算呢?首先我们知道左边的区间的x肯定是小于右区间,我们其实已经可以不用

    考虑X的影响了,所以我们对这连个区间对Y进行排序,那么我们要的三维偏序应该是,右边每一个值y,对应左边比右边的y小的值,我们把它的Z加入树状数组,像维护二维偏序一样维护

    那么最后每个点贡献我们就可以得到,但是维护了每一段后,我们应该把树状数组进行清空,不然下次计算就有问题了。

    注意要去重!!!

    #include<iostream>
    #include<stdio.h>
    #include<string.h>
    #include<algorithm>
    #include<vector>
    #define LL long long
    using namespace std;
    const int maxx = 3e6+6;
    struct node{
      int x,y,z,cnt,ans;
    }flower[maxx];
    int sum[maxx];
    int num[maxx];
    int n,k,tot;
    int lowbit(int x){
      return x&(-x);
    }
    void add(int x,int w){
       for (int i=x;i<=k;i+=lowbit(i)){
          sum[i]+=w;
       }
    }
    int query(int x){
       int ans=0;
       for (int i=x;i;i-=lowbit(i)){
           ans+=sum[i];
       }
       return ans;
    }
    bool cmpy(node a,node b){
       if(a.y==b.y){
          if (a.z==b.z){
             return a.x<b.x;
          }
          return a.z<b.z;
       }
       return a.y<b.y;
    }
    bool cmpx(node a,node b){
       if(a.x==b.x){
          if (a.y==b.y){
            return a.z<b.z;
          }
          return a.y<b.y;
       }
       return a.x<b.x;
    }
    void cdq(int l,int r){
       if(l==r){
          flower[l].ans+=flower[l].cnt-1;
          return ;
       }
       int mid=(l+r)>>1;
       cdq(l,mid);
       cdq(mid+1,r);
       sort(flower+l,flower+mid+1,cmpy);
       sort(flower+mid+1,flower+r+1,cmpy);
       int j=l;
       for (int i=mid+1;i<=r;i++){
          while(j<=mid && flower[j].y<=flower[i].y){
              add(flower[j].z,flower[j].cnt);
              j++;
          }
          flower[i].ans+=query(flower[i].z);
       }
       for (int i=l;i<j;i++){
         add(flower[i].z,-flower[i].cnt);
       }
    }
    int main(){
      scanf("%d%d",&n,&k);
      for (int i=1;i<=n;i++){
         scanf("%d%d%d",&flower[i].x,&flower[i].y,&flower[i].z);
         flower[i].ans=1;
      }
      sort(flower+1,flower+1+n,cmpx);
      int tot=0;
      for (int i=1;i<=n;i++){
          if(i!=1 && flower[i].x==flower[i-1].x && flower[i].y==flower[i-1].y && flower[i].z==flower[i-1].z){
              flower[tot].cnt++;
          }else {
              tot++;
              flower[tot]=flower[i];
              flower[tot].cnt=1;
          }
      }
    //  for (int i=1;i<=tot;i++){
    //    cout<<flower[i].x<<" "<<flower[i].y<<" "<<flower[i].z<<" "<<flower[i].cnt<<" "<<flower[i].ans<<endl;
    //  }
      cdq(1,tot);
      for (int i=1;i<=tot;i++){
         num[flower[i].ans]+=flower[i].cnt;
      }
      for (int i=1;i<=n;i++){
        printf("%d
    ",num[i]);
      }
      return 0;
    }
    /*
    1 2 2 1 1
    2 2 1 1 1
    2 2 3 2 1
    2 3 3 0 1
    3 2 1 2 1
    3 2 2 0 1
    3 3 3 0 1
    */
    有不懂欢迎咨询 QQ:1326487164(添加时记得备注)
  • 相关阅读:
    详解Webpack-dev-server的proxy用法
    .sync修饰符
    [Vue]createElement参数
    ElementUi学习笔记
    A5000项目阅读笔记
    webpack学习-10天搞定webpack4
    bhuilder 采坑日记-大小写问题
    angularjs:$$animateJs is not a function 错误
    webpack4 Cannot find module '@babel/core'
    算法-图论-最短路径-Dijsktra算法
  • 原文地址:https://www.cnblogs.com/bluefly-hrbust/p/11461302.html
Copyright © 2020-2023  润新知