CDQ分治学习笔记
CDQ 分治#
分治可以用来解决多维偏序问题
它是一个在线算法
二维偏序#
给你 个元素,每个元素有两个属性 和 ,定义 表示 且 的元素数量
求 的数量
思路:
我们可以以 为第一关键字, 为第二关键字从小到大排序
排序后对于第 个数我们找前 个数中 的 的个数
搞一个树状数组维护即可,复杂度
三维偏序#
三维偏序的问题无非就是在二维偏序上加了一维
我们考虑先按第一维 排序
然后第二维考虑归并排序,第三维用树状数组
我们在归并排序的时候考虑 对 的贡献
由于我们已经对第一维 排序过了,因此归并排序时无论 怎样被打乱, 中所有元素的 值是不小于 的,第二维是 的
在满足前两维均有序的条件下,我们可以用类似于二维偏序的解法搞一个树状数组统计就行了
这样的时间复杂度是 的
要对元素进行去重
code:
#include<bits/stdc++.h>
using namespace std;
#define lowbit(x) x&-x
const int N=1e5+5;
inline int read(){
int x=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-') f=-1;ch=getchar();}
while(isdigit(ch)){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
return x*f;
}
int n,m;
int ans[N],c[N];
struct num{
int a,b,c,w,f;
inline bool operator < (const num A){
return a==A.a?(b==A.b?c<A.c:b<A.b):a<A.a;
}
}a[N],tmp[N];
inline void add(int x,int k){
for(;x<=m;x+=lowbit(x))
c[x]+=k;
}
inline int query(int x){
int res=0;
for(;x;x-=lowbit(x)) res+=c[x];
return res;
}
inline void CDQ(int l,int r){
if(l==r) return;
int mid=l+r>>1;
CDQ(l,mid),CDQ(mid+1,r);
int i=l,j=mid+1,cnt=l-1;
while(i<=mid&&j<=r){
if(a[i].b<=a[j].b) add(a[i].c,a[i].w),tmp[++cnt]=a[i++];
else a[j].f+=query(a[j].c),tmp[++cnt]=a[j++];
}
while(i<=mid) add(a[i].c,a[i].w),tmp[++cnt]=a[i++];
while(j<=r) a[j].f+=query(a[j].c),tmp[++cnt]=a[j++];
for(i=l;i<=mid;++i) add(a[i].c,-a[i].w);
for(i=l;i<=r;++i) a[i]=tmp[i];
}
signed main(){
n=read(),m=read();
for(int i=1;i<=n;++i)
a[i].a=read(),a[i].b=read(),a[i].c=read(),a[i].w=1;
sort(a+1,a+n+1);
int r=1;
for(int i=2;i<=n;++i){
if(a[i].a==a[r].a&&a[i].b==a[r].b&&a[i].c==a[r].c) ++a[r].w;
else a[++r]=a[i];
}
CDQ(1,r);
for(int i=1;i<=r;++i) ans[a[i].f+a[i].w-1]+=a[i].w;
for(int i=0;i<n;++i) cout<<ans[i]<<endl;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探