三维偏序
cdq 分治:
一个长度为
- 什么是
分治思想?
-
假设我们现在要求的是
这个区间的所有点对所对应的答案。 -
令中点
-
将点对分为三类:
1.
和 均在 中的 点对2.
在 中, 在 中的 点对3.
和 均在 的 的点对 -
此时对 1、3 类点对进行递归计算,并设法求出第 2 种点对的答案。
Solution:
回到 P3810 【模板】三维偏序 中,在本题中
首先简化一下问题,将点按
那么我们考虑在
此时我们为了方便处理,对左右两半分别按
维护两个指针
记得去重。
#include<bits/stdc++.h> #define int long long using namespace std; const int N=1e5+10; int n,m; struct point{ int x,y,z; int cnt,ans; }p[N],tmp[N]; struct BIT{ int t[N<<1]; int lowbit(int x){return x&-x;} void add(int x,int k){ while(x<=m){ t[x]+=k; x+=lowbit(x); } return; } int sum(int x){ int ret=0; while(x>0){ ret+=t[x]; x-=lowbit(x); } return ret; } }tree; bool cmp(struct point p1,struct point p2){ if(p1.x!=p2.x)return p1.x<p2.x; if(p1.y!=p2.y)return p1.y<p2.y; return p1.z<p2.z; } void cdq(int l,int r){ if(l>=r)return; int mid=(l+r>>1); cdq(l,mid);cdq(mid+1,r); int cnt=0; int i=l,j=mid+1; while(i<=mid&&j<=r){ if(p[i].y<=p[j].y)tree.add(p[i].z,p[i].cnt),tmp[++cnt]=p[i++]; else{ p[j].ans+=tree.sum(p[j].z); tmp[++cnt]=p[j++]; } } while(i<=mid)tree.add(p[i].z,p[i].cnt),tmp[++cnt]=p[i++]; while(j<=r)p[j].ans+=tree.sum(p[j].z),tmp[++cnt]=p[j++]; for(int i=l;i<=mid;i++)tree.add(p[i].z,-p[i].cnt); for(int i=l;i<=r;i++)p[i]=tmp[i-l+1]; return; } int res[N]; signed main(){ std::ios::sync_with_stdio(false); cin.tie(0);cout.tie(0); cin>>n>>m; for(int i=1;i<=n;i++)cin>>p[i].x>>p[i].y>>p[i].z,p[i].cnt=1; sort(p+1,p+n+1,cmp); int tmpcnt=1; for(int i=2;i<=n;i++){ if(p[i].x==p[tmpcnt].x&&p[i].y==p[tmpcnt].y&&p[i].z==p[tmpcnt].z){ p[tmpcnt].cnt++; continue; } p[++tmpcnt]=p[i]; } cdq(1,tmpcnt); //for(int i=1;i<=n;i++)cout<<p[i].x<<" "<<p[i].y<<" "<<p[i].z<<" "<<f[i]<<" "<<p[i].cnt<<endl; for(int i=1;i<=tmpcnt;i++)res[p[i].ans+p[i].cnt-1]+=p[i].cnt; for(int i=0;i<n;i++)cout<<res[i]<<"\n"; return 0; }
本文作者:Little_corn
本文链接:https://www.cnblogs.com/little-corn/p/18157476
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步