CDQ分治

CDQ分治是一种分治类算法,可以解决三维以及多维偏序 ( CDQ套CDQ套CDQ套CDQ套CDQ套CDQ套CDQ套CDQ套CDQ套CDQ套CDQ套CDQ套CDQ套CDQ套CDQ套CDQ套CDQ套CDQ套CDQ套CDQ套CDQ套CDQ套CDQ套CDQ套CDQ套CDQ套CDQ套CDQ套CDQ套CDQ ) 问题。

其思想类似于归并排序,在子问题对当前问题有贡献时可以使用QAQ 例如板题陌上花开(三位偏序) (我不会CDQ套CDQ)首先我们按照\(a\)升序排序 显然接下来我们需要解决的问题就是\(b,c\) 的偏序问题了 因为我们已经按照a升序排序了 所以在分治后的左区间在满足\(b_l<b_r\)&&\(c_l<c_r\)的 时候会对右区间产生贡献 我们可以分别对左区间,右区间按照\(b\)排序,然后用树状数组维护\(c\)就可以了

注意要去重,因为如果相同的数却被分在了左右区间 会产生意想不到的结果哦QAQ

另外如果将区间按照\(b\)排序了 那么如果\(b_r<b_l\) 就可以直接更新\(b_r\)对应的\(data\)\(ans\)了。因为显然\(b_{l+1}>b_r\) (毕竟按照b排序了)

#include <cstdio>
#include <algorithm>
#include <cstring>
#include <iostream>
#include <cmath>
using namespace std;
const int maxn=100100;
int read(){
	int x=0,f=1;char ch=getchar();
	while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();}
	return x*f;
}
struct node{
	int a,b,c,cnt,ans;
	#define a(x) num[x].a
	#define b(x) num[x].b
	#define c(x) num[x].c 
}num[maxn],data[maxn];
inline bool cmpl(node x,node y){return x.a<y.a || (x.a==y.a && (x.b<y.b || (x.b==y.b && x.c<y.c)));}
inline bool cmpll(node x,node y){return x.b<y.b || (x.b==y.b && x.c<y.c);}
int nn,n,k,tot,tree[maxn<<1],shawn[maxn<<1];
void add(int x,int y){
	for(;x<=k;x+=(x&-x)){
		tree[x]+=y;
	}
}
int query(int x){
	int sum=0;
	for(;x;x-=(x&-x)){
		sum+=tree[x];
	}
	return sum;
}
void cdq(int l,int r){
	if(l==r) return ;
	int mid=l+r>>1;
	cdq(l,mid);cdq(mid+1,r);
	sort(data+l,data+mid+1,cmpll);sort(data+mid+1,data+r+1,cmpll);
	int i=mid+1,j=l;
	for(;i<=r;i++){
		while(data[j].b<=data[i].b && j<=mid){
			add(data[j].c,data[j].cnt);j++;
		}
		data[i].ans+=query(data[i].c);
	}
	for(i=l;i<j;i++)
		add(data[i].c,-data[i].cnt);
}
int main(){
	nn=read();k=read();
	for(int i=1;i<=nn;i++){
		a(i)=read();b(i)=read();c(i)=read();
	}
	sort(num+1,num+1+nn,cmpl);
	for(int i=1;i<=nn;i++){
		tot++;
		if(a(i)!=a(i+1) || b(i)!=b(i+1) || c(i)!=c(i+1)){data[++n]=num[i];data[n].cnt=tot;tot=0;}
	}
	cdq(1,n);
	for(int i=1;i<=n;i++){
		shawn[data[i].ans+data[i].cnt-1]+=data[i].cnt;
	}
	for(int i=0;i<nn;i++)
		printf("%d\n",shawn[i]);
	return 0;
}
posted on 2019-11-08 19:28  萌德真帅  阅读(203)  评论(0编辑  收藏  举报