ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

三维偏序——cdq分治

2019-10-27 14:53:35  阅读:212  来源: 互联网

标签:偏序 10 ch int res 分治 bi cdq define


题目:

  有 n 个元素,第 i 个元素有 ai 、bi 、ci 三个属性,设 f(i) 表示满足 aj ≤ ai 且 bj ≤ bi 且 cj ≤ ci 的 j 的数量。对于 d∈[0,n),求 f(i)=d  的 i 的数量。

题解:

  可以对第一维a进行排序(O(nlogn)),然后对第二维进行归并排序(O(nlogn)),在归并时对于 b<= bj可以将对应的 c的个数加进树状数组(O(nlogk)),在bi b时统计小于cj的数量,最后回溯的时候不要忘了清空树状数组。对于重复的数,可以先进行去重,详见代码。

p3810AC代码:

  1 #include <bits/stdc++.h>
  2 #define numm ch-48
  3 #define pn putchar('\n')
  4 #define pd putchar(' ')
  5 #define debug(args...) cout<<#args<<"->"<<args<<endl
  6 //#define bug cout<<"*******************"<<endl
  7 using namespace std;
  8 template<typename T>
  9 void read(T &res) {
 10     char ch;bool flag=false;
 11     while(!isdigit(ch=getchar()))(ch=='-')&&(flag=true);
 12     for(res=numm;isdigit(ch=getchar());res=(res<<1)+(res<<3)+numm);
 13     flag&&(res=-res);
 14 }
 15 template<typename T>
 16 void write(T x) {
 17     if(x<0) x=-x,putchar('-');
 18     if(x>9) write(x/10);
 19     putchar(x%10+48);
 20 }
 21 typedef long long ll;
 22 const int maxn=100000+10;
 23 const int inf=0x3f3f3f3f;
 24 struct node {
 25     int a,b,c;      ///a,b,c三个变量
 26     int ans,cnt;
 27     bool operator<(const node &x) const{
 28         if(a!=x.a) return a<x.a;
 29         else if(b!=x.b) return b<x.b;
 30         else if(c!=x.c) return c<x.c;
 31     }
 32 }e[maxn],temp[maxn];///temp[]:存放归并后的数
 33 int tree[maxn<<1],k,res[maxn];  ///tree[]:树状数组
 34 int lowbits(int x) {
 35     return x&-x;
 36 }
 37 void add(int i,int v) {
 38     while(i<=k) {
 39         tree[i]+=v;
 40         i+=lowbits(i);
 41     }
 42 }
 43 int query(int i) {
 44     int ans=0;
 45     while(i) {
 46         ans+=tree[i];
 47         i-=lowbits(i);
 48     }
 49     return ans;
 50 }
 51 void cdq(int l,int r) {
 52     if(l==r) {
 53         e[l].ans+=e[l].cnt-1;  ///不要把自己算进去,-1
 54         return ;
 55     }
 56     int mid=l+r>>1;
 57     cdq(l,mid);
 58     cdq(mid+1,r);
 59     int i=l,j=mid+1,op=l;///双指针进行归并
 60     while(j<=r) {   ///把右边大于左边的都统计一次
 61         while(i<=mid&&e[i].b<=e[j].b) {
 62             add(e[i].c,e[i].cnt);   ///把个数加到对应的权值之上
 63             temp[op++]=e[i];
 64             i++;
 65         }
 66         e[j].ans+=query(e[j].c);
 67         temp[op++]=e[j];
 68         j++;
 69     }
 70     for(int j=l;j<i;j++)    ///清空树状数组
 71         add(e[j].c,-e[j].cnt);
 72     while(i<=mid)   ///左边(i那部分)有可能没算完
 73         temp[op++]=e[i],i++;
 74 
 75     for(i=l;i<=r;i++)///把排序后的temp赋值给e
 76         e[i]=temp[i];
 77 }
 78 int main()
 79 {
 80     int n;
 81     read(n);read(k);///k:a,b,c的大小上限
 82     for(int i=1;i<=n;i++)
 83         read(e[i].a),read(e[i].b),read(e[i].c);
 84     sort(e+1,e+1+n);
 85     int cnt=1,tot=0;
 86     for(int i=2;i<=n;i++) { ///去重
 87         if(e[i-1].a^e[i].a||e[i-1].b^e[i].b||e[i-1].c^e[i].c) {
 88             e[++tot]=e[i-1];
 89             e[tot].cnt=cnt;
 90             e[tot].ans=0;
 91             cnt=1;
 92         }
 93         else cnt++;
 94     }
 95     e[++tot]=e[n];
 96     e[tot].cnt=cnt;
 97     e[tot].ans=0;
 98     cdq(1,tot);
 99     for(int i=1;i<=tot;i++)
100         res[e[i].ans]+=e[i].cnt;///最后的答案为ans的数有多少个,所以加上cnt
101     for(int i=0;i<n;i++)
102         write(res[i]),pn;
103     return 0;
104 }
View Code

 

标签:偏序,10,ch,int,res,分治,bi,cdq,define
来源: https://www.cnblogs.com/wuliking/p/11747524.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有