D-CDQ分治

lyrrr發表於2024-08-29

放一個cdq分治板子。
是洛谷陌上花開程式碼搬過來的。感覺要點在於去重(完全相同的點),沒了。

#include<bits/stdc++.h>
using namespace std;
#define ls(x) (x<<1)
#define rs(x) ((x<<1)+1)
#define lowbit(x) (x&(-x)) 
const int maxn=2e5+10;
struct Node{
	int a,b,c,id;
	bool vis=0;
}node[maxn];
int f[maxn],t[maxn*2],num[maxn],bj[maxn];

bool cmp(const Node &x,const Node &y){
	if(x.a!=y.a)return x.a<y.a;
	if(x.b!=y.b)return x.b<y.b;
	return x.c<y.c;
}
bool cmp2(const Node &x,const Node &y){
	if(x.b!=y.b)return x.b<y.b;
	if(x.c!=y.c)return x.c<y.c;
	return x.a<y.a;
}
void modify(int x,int k){
	while(x<maxn){
		t[x]+=k;
		x+=lowbit(x);
	}
	return;
}
int que(int x){
	int res=0;
	while(x>0){
		res+=t[x];
		x-=lowbit(x);
	}
	return res;
}
void merge(int l,int mid,int r){
	sort(node+l,node+r+1,cmp2);
	for(int i=l;i<=r;i++){
		//cout<<node[i].a<<endl;;
		if(node[i].a<=mid)modify(node[i].c,1);
		else f[node[i].id]+=que(node[i].c);
	}
	for(int i=l;i<=r;i++)
		if(node[i].a<=mid)modify(node[i].c,-1);
	
}
void cdq(int l,int r){
	if(l==r)return;
	int mid=(l+r)>>1;
	cdq(l,mid);
	cdq(mid+1,r);
	merge(l,mid,r);
}
signed main(){
	int n,k;cin>>n>>k;
	for(int i=1;i<=n;i++){
		cin>>node[i].a>>node[i].b>>node[i].c;
		node[i].id=i;
	}	
	sort(node+1,node+n+1,cmp);
	for(int i=1;i<=n;){
		int j=i+1;
		while(j<=n&&node[j].a==node[i].a&&node[j].b==node[i].b&&node[j].c==node[i].c)
			j++;
		while(i<j)
			bj[node[i].id]=node[j-1].id,i++;
	}
	for(int i=1;i<=n;i++)node[i].a=i;
	cdq(1,n);
	for(int i=n;i>=1;i--){
		num[f[bj[node[i].id]]]++;
	}
	for(int i=0;i<n;i++)cout<<num[i]<<"\n";
}

相關文章