cdq分治是一种常用的降维手段,可以解决偏序问题。

题目

给定\(n\)个三元组\((x, y, z)\),给定一个\(f(a)\),表示所有元素\(b\)(自己不算),它的\(x,y,z\)均小于等于\(a\)的对应\(x,y,z\),求\([0, n)\)中每种\(f\)值的个数。

\(n \leq 100000\)

\(x, y, z \leq 200000\)

简单模型

一维:仅有\(x\):按\(x\)排序即可。

二维:有\((x, y)\),按先\(x\)后\(y\)顺序排序,然后将\(y\)值用树状数组统计。

三维偏序:cdq分治解法

思想:类似归并排序

现将元素按\(x, y, z\)升序排序。(降一维\(x\)),然后还剩下两维,可以用归并排序的思想消去一维。

将待处理的序列分成两份,分别按\(y\)值排序和统计。(分治思想,类似逆序对)

统计:两部分中:左半部分\(x\)都比右半部分的小,因此只需要统计右半部分对左半部分的贡献即可。用树状数组统计\(z\)值。因为两边\(y\)值都是有序的,所以维护一个左边的指针,每次将\(y\)值小于等于右边当前位置的元素扔进树状数组统计,然后统计\(z\)值比它小的即可。

int p = l; //前指针
for(int i=mid+1; i<=r; i++){ //后半部分用前半部分更新for(;a[p].y<=a[i].y && p<=mid; ++p) upd(a[p].z, a[p].cnt); //把y比它小的加进树状数组,注意cnta[i].ans += ask(a[i].z); //查询x, y, z均比a[i]小的
}

时间复杂度:\(O(n log ^ 2 n)\)

注意事项

  1. 处理前必须去重,因为是小于等于,要防止同样的元素被切进两个区域导致无法统计答案。最后统计答案时,要针对\(cnt\)再进行更改(详见代码)
  2. 不能每次新建一个树状数组或清空树状数组,要一步一步撤销操作,否则每次都要花费\(O(n)\)时间清空,总时间复杂度变成\(O(n^2)\)。

Code

已经省略快读,快输

#include <cstdio>
#include <cctype>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 100005, K = 200005;
typedef long long ll;
struct elem{int x, y, z, ans, cnt;
}a[N], tmp[N];
int ans[N];
bool cmpx(elem a, elem b){return (a.x == b.x)?((a.y==b.y)?(a.z<b.z):(a.y<b.y)):(a.x<b.x);} //先x后y,z排序
bool cmpy(elem a, elem b){return (a.y == b.y)?(a.z<b.z):(a.y<b.y);} //先y后z排序
int n, k;
int tr[K];
inline void upd(int p, int x){ //树状数组更新if(p == 0) return ;for(;p<=k; p+=p&-p) tr[p] += x;
}
inline int ask(int p){ //树状数组前缀和int ans = 0;for(;p; p-=p&-p) ans+=tr[p];return ans;
}void solve(int l, int r){ //cdq分治if(l == r) return ;int mid = (l + r) >> 1;solve(l, mid); solve(mid+1, r); //两边排序,统计int p = l; //前指针for(int i=mid+1; i<=r; i++){ //后半部分用前半部分更新for(;a[p].y<=a[i].y && p<=mid; ++p) upd(a[p].z, a[p].cnt); //把y比它小的加进树状数组,注意cnta[i].ans += ask(a[i].z); //查询x, y, z均比a[i]小的}for(int i=l; i<p; i++) upd(a[i].z, -a[i].cnt); //清空,注意没有用的不清空merge(a+l, a+mid+1, a+mid+1, a+r+1, tmp, cmpy); //归并,同归并排序for(int i=l; i<=r; i++) a[i] = tmp[i - l];
}int main(){freopen("3810.in", "r", stdin);freopen("3810.out", "w", stdout);in(n); in(k);for(int i=1; i<=n; i++) in(a[i].x), in(a[i].y), in(a[i].z), a[i].cnt = 1;sort(a+1, a+1+n, cmpx);int p = 1;for(int i=2; i<=n; i++){ //去重,统计cntif(a[i].x == a[i-1].x && a[i].y == a[i-1].y && a[i].z == a[i-1].z) ++a[p].cnt;else a[++p] = a[i];}solve(1, p);for(int i=1; i<=p; i++) ans[a[i].ans + a[i].cnt - 1] += a[i].cnt;//有相同的答案会增加,注意自己不算for(int i=0; i<n; i++) write(ans[i]), putchar('\n');return 0;
}

转载于:https://www.cnblogs.com/RiverHamster/p/cdq-3dPartialOrder.html

三维偏序:CDQ分治相关推荐

  1. 三维偏序/cdq分治/

    三维偏序---cdq分治 cdq分治概述 二维偏序概述 二维偏序例题分析 三维偏序概述 例题分析 cdq分治概述 前置知识:(如果不懂要先去了解分治) > 分治: > 分而治之,将原问题不 ...

  2. BZOJ 2244 [SDOI2011]拦截导弹 (三维偏序CDQ+线段树)

    题目大意: 洛谷传送门 不愧为SDOI的duliu题 第一问?二元组的最长不上升子序列长度?裸的三维偏序问题,直接上$CDQ$ 由于是不上升,需要查询某一范围的最大值,并不是前缀最大值,建议用线段树实 ...

  3. BZOJ3262/Luogu3810 陌上花开 (三维偏序,CDQ)

    一个下午的光阴之死,凶手是细节与手残. 致命的一枪:BIT存权值时: for(; x <= maxx; x += x&-x) t[x] += w;//for(; x <= n; x ...

  4. [偏序关系与CDQ分治]【学习笔记】

    组合数学真是太棒了 $CDQ$真是太棒了(雾 参考资料: 1.<组合数学> 2.论文 课件 很容易查到 3.sro __stdcall 偏序关系 关系: 集合$X$上的关系是$X$与$X$ ...

  5. CDQ分治 + 树状数组 ---- C. Goodbye Souvenir(三维偏序+思维)

    题目链接 题目大意: 给定长度为nnn的数组, 定义数字XXX在[l,r][l,r][l,r]内的值为数字XXX在[l,r][l,r][l,r]内最后一次出现位置的下标减去第一次出现位置的下标 给定m ...

  6. HDU - 5517 Triple(三维偏序-二维树状数组/CDQ分治)

    题目链接:点击查看 题目大意:给出 n 个二元对 ( a , b ) 和 m 个三元对 ( c , d , e ),对于所有 b == e 的二元对和三元对,可以通过某种运算形成一个新的三元对 ( a ...

  7. 洛谷 - P3810 【模板】三维偏序(陌上花开)(CDQ分治套树状数组)

    题目链接:点击查看 题目大意:给出 n 个点,每个点有三个属性 a , b , c ,对于每个点 i 来说,求出有多少个 j 满足 a[ j ] <= a[ i ] && b[ ...

  8. 【原创】从BZOJ2683 简单题中 整 CDQ分治解决三维偏序

    CDQ分治 题目描述 你有一个N*N的棋盘,每个格子内有一个整数,初始时的时候全部为0,现在需要维护两种操作: 命令 参数限制 内容 1 x y A 1<=x,y<=N,A是正整数 将格子 ...

  9. 分治算法,逆序对,三维偏序与CDQ分治

    分治算法基本思想 当我们求解某些问题时,由于这些问题要处理的数据相当多,或求解过程相当复杂,使得直接求解法在时间上相当长,或者根本无法直接求出. 对于这类问题,我们往往先把它分解成几个子问题,找到求出 ...

  10. hdu5618 (三维偏序,cdq分治)

    给定空间中的n个点,问每个点有多少个点小于等于自己. 先来分析简单的二维的情况,那么只要将x坐标排序,那么这样的问题就可以划分为两个子问题,,这样的分治有一个特点,即前一个子问题的解决是独立的,而后一 ...

最新文章

  1. c索引超出了数组界限_Lua数组、Lua迭代器
  2. 【转】NSDictionary以及NSMutableDictionary的用法
  3. 上传文件大小超过服务器限制是什么意思,求助:文件上传 当文件大小大于限制时弹出提示框...
  4. ZigBee网络数据传递流程_基于ZigBee—WSN的温湿度监测系统
  5. uva 10479——The Hendrie Sequence
  6. 如何安装python3.8_Python安装1 —— Python3.8的安装
  7. W3C发布DRM作为推荐方案
  8. 冬小麦病虫害的高光谱识别方法研究
  9. html5页面的手势,HTML5单页面手势滑屏切换如何实现
  10. NLP学习—13.Seq2eq在机器翻译中的实战(bleu指标的代码实现)
  11. 面试字节、阿里等大厂后,总结了今年的 Java 面试必问的微服务面试题(含答案)
  12. mysql表空间加密
  13. 瑞幸咖啡上市被评“蒙眼狂奔”,CEO钱治亚回答:狂奔是真的,但并非蒙眼
  14. c new java_“邻避设施”的种类主要包括()。
  15. ChatGPT 之父传奇:8岁学编程,16岁出柜,37岁颠覆科技圈,网友:“天选 CEO!”...
  16. FLV 格式:为什么直播首选这个流媒体格式?丨音视频基础
  17. Mock server是什么
  18. dd_engi的背包九讲(新版转载)
  19. 谁在“接盘”造车新势力?
  20. 怎么分析淘宝店铺市场竞争选品 淘宝产品选品具体该怎么做

热门文章

  1. java小数正负数据类型_Java - day001 - 8种基本数据类型
  2. 阿里巴巴《rocketmq开发指南》_主流消息中间件优劣:ActiveMQ,RabbitMQ,Kafka,RocketMQ...
  3. word2vec字向量_Anything2Vec:将Reddit映射到向量空间
  4. 索佳电子水准数据传输软件_安徽铜陵磁致伸缩式静力水准仪公司
  5. oracle 64位使用plsql,64位操作系统使用plsql
  6. eos linux开发语言,EOSIO与Linux之间的区别
  7. barplot函数--R语言
  8. mongodb 系列 ~ mongo的两种引擎对比
  9. 伸缩Kubernetes到2500个节点中遇到的问题和解决方法
  10. html静态页面作跳转