找回密码
 立即注册
首页 业界区 安全 CDQ分治

CDQ分治

仇华乐 2025-6-27 17:48:45
前言

这个东西吧,我觉得吧,建议别学,过于困难。其实寒假学过,但是没有一个字是自己写的。
知识点

前置知识之求逆序对个数

给定 \(n\) 个数,每个数都有一个权值 \(a_i\),求满足 \(i\le j\) 同时 \(a_i\geq a_j\) 的点对个数。
显然,我们只需按顺序遍历一遍,用树状数组或者线段树维护一下在当前点之前,大于等于当前 \(a_i\) 的点个数即可。
至于它为什么对吧,显然你按顺序遍历就一定满足 \(i\neq j\),同时你维护的就是 \(a_j \geq a_i\),所以正确性十分显然啊。
正文

给定 \(n\) 个数,每个数有3个值 \(u_i,v_i,w_i\),求满足 \(u_i\le u_j,v_i\le v_j,w_i\le w_j\)的点对个数。
假如令 \(w_i=1\),那么答案就很显然了,我们只需要把它当成逆序对来算就可以。
同时,我们灵光一现,发现还有一个东西叫做归并排序,同时,归并排序前对 \(u\) 排序,就一定可以保证左半边的 \(u_i\) 值是小于等于右半边的,同时,归并排序本身就可以维护使 \(v\) 有序,因此,我们只需要再用树状数组维护一下 \(w\) 的顺序即可。
所以 cdq分治的思路就很显然了,分三层维护其有序性,首先在外面对 \(u\) 排个序,然后再使用归并排序,通过合并维护 \(v\) 的顺序,最后在归并排序过程中,我们考虑用个什么东西维护最后一维就好了。
[code]#include#define int long long #define lowbit(x) (x&(-x))using namespace std;int n,k,ans=0;const int N=2e5+100;int c[N],sum[N];struct node {        int x,y,z,ans,cnt;        friend bool operator
您需要登录后才可以回帖 登录 | 立即注册