window.cnblogsConfig = { homeTopImg: [ "https://cdn.luogu.com.cn/upload/image_hosting/clcd8ydf.png", "https://cdn.luogu.com.cn/upload/image_hosting/clcd8ydf.png" ], }

CDQ分治

CDQ分治

它是一种非常巧妙地方法。

用分治的思想处理三维偏序一类的问题:

处理的问题如下:模板

有 $ n $ 个元素,第 $ i $ 个元素有 $ a_i,b_i,c_i $ 三个属性,设 $ f(i) $ 表示满足 $ a_j \leq a_i $ 且 $ b_j \leq b_i $ 且 $ c_j \leq c_i $ 且 $ j \ne i $ 的 \(j\) 的数量。

对于 $ d \in [0, n) $ ,求 $ f(i) = d $ 的数量。

也就是对于每一个三元组 \(i\) 看有多少个完全小于他的三元组 \(j\)

数据范围 \(n \le 2\times 10^5\)

显然暴力会不过去。

只能考虑一些 \(n \log n\)\(n \log^2 n\) 的做法。

首先,先把第一维排序了。

这样,只用考虑 \(b_i\)\(c_i\) 了。

那我们考虑如何处理 \(b_i\)

类似归并的方法,分而治之,分治。就是对于 \([l,r]\) 的子区间我们先处理 \([l,mid]\)\([mid+1,r]\) 两个区间,然后将其 \(O(r-l)\) 的时间复杂度合并。很简单的策略,分别在两个子区间内放两个指针,那边小就加入那边,因为如果 \(A_i\) 他是比 \(B_j\) 小的,那么 \(A\) 目前也排序了,所以也是 \(A\) 中最小的,也就是 \(A\)\(B\) 合并后最小的,因此直接判断然后去加即可。

这样,\(b_i\) 也处理好了,我们就可以用树状数组维护一下 \(c_i\) 的数量,然后就可以求出此时比 \(c_i\) 小的 \(c_j\) 有多少个,由于在线处理,所以说,之前出现的 \(a_i\)\(b_i\) 都是应该符合小于现在的这个三元组的。

于是,在线(边跑边记录)处理完之后,再依次输出答案。

int n,k,m;
struct node{int a,b,c;};
struct data{node a;int cnt,ans;};
node a[N];
struct data b[N];
int t[N<<1];
void add(int x,int val){while(x<=k)t[x]+=val,x+=(x&-x);}
int query(int x){int res=0;while(x)res+=t[x],x-=(x&-x);return res;}
bool node_cmp(node a,node b){
	if(a.a != b.a) return a.a<b.a;
	if(a.b != b.b) return a.b<b.b;
	return a.c<b.c;
}bool data_cmp(struct data a,struct data b){
	if(a.a.b != b.a.b) return a.a.b<b.a.b;
	return a.a.c<b.a.c;
}void cdq(int l,int r){
	if(l==r)return ;
	int mid=(l+r)>>1,x=l;
	cdq(l,mid),cdq(mid+1,r);
	sort(b+l,b+1+mid,data_cmp),sort(b+1+mid,b+1+r,data_cmp);
	For(i,mid+1,r){
		while(x<=mid&&b[x].a.b<=b[i].a.b) add(b[x].a.c,b[x].cnt),x++;
		b[i].ans+=query(b[i].a.c);
	}For(i,l,x-1){
		add(b[i].a.c,-b[i].cnt);//清空还原操作
	}
}int ans[N];
void solve(){
	cin>>n>>k;
	For(i,1,n)cin>>a[i].a>>a[i].b>>a[i].c;
	sort(a+1,a+1+n,node_cmp);
	For(i,1,n){
		if(a[i].a!=a[i-1].a||a[i].b!=a[i-1].b||a[i].c!=a[i-1].c) b[++m].a=a[i];
		b[m].cnt++;	
	}
	cdq(1,m);
	For(i,1,m)ans[b[i].ans+b[i].cnt]+=b[i].cnt;
	For(i,1,n)cout<<ans[i]<<endl;
}
posted @ 2024-04-24 19:33  gsczl71  阅读(12)  评论(0编辑  收藏  举报