CDQ 分治玄关求条
查看原帖
CDQ 分治玄关求条
637073
wujingfey楼主2024/11/6 21:37
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+7;
int n,m,k,f[N],ans[N],tr[N];
int lowbit(int x){
	return x&(-x);
}
void add(int p,int v){
	while(p<=k){
		tr[p]+=v;
		p+=lowbit(p);
	}
}
int sum(int p){
	int res=0;
	while(p){
		res+=tr[p];
		p-=lowbit(p);
	}
	return res;
}
struct NODE{
	int x,y,z,cnt,num;
}aa[N],a[N];
bool operator !=(NODE a1,NODE a2){
	if(a1.x==a2.x && a1.y==a2.y &&a1.z==a2.z) return false;
	else return true;
}
bool cmpy(NODE a1,NODE a2){
	return a1.y<a2.y;
}
bool cmpx(NODE a1,NODE a2){
	return a1.x<a2.x;
}
void CDQ(int l,int r){
	if(l==r) return;
	int mid=(l+r)>>1;
	CDQ(l,mid);
	CDQ(mid+1,r);
	//分治处理子问题 
	sort(a+l,a+mid+1,cmpy);
	sort(a+mid+1,a+r+1,cmpy);
	//按照y排序 
	int i=l,j=mid+1;
	for(;j<=r;j++){
		for(;i<=mid && a[i].y<=a[j].y;i++){
			//筛选 a[i].y<=a[j].y 
			add(a[i].z,a[i].cnt);
		}
		a[j].num+=sum(a[j].z);
		//进一步筛选 a[i].z<=a[j].z 的数量 
	}
	for(j=l;j<i;j++){//memset要炸 
		add(a[j].z,-a[j].cnt);
	}
}
signed main(){
	ios::sync_with_stdio(false);
	cin.tie(0);
	cin>>n>>k;
	for(int i=1;i<=n;i++){
		int x,y,z;
		cin>>aa[i].x>>aa[i].y>>aa[i].z;
	}
	int tot=0;
	sort(aa+1,aa+1+n,cmpx);
	for(int i=1;i<=n;i++){
		tot++;
		if(aa[i]!=aa[i+1]){
			a[++m]=aa[i];
			a[m].cnt=tot;
			tot=0;
		}
	}
	CDQ(1,m);
	for(int i=1;i<=m;i++){//ai和aj如果相同也要算在答案内 
		ans[a[i].num+a[i].cnt-1]+=a[i].cnt;
	}
	for(int i=0;i<n;i++){
		cout<<ans[i]<<"\n";
	}
	return 0;
}
2024/11/6 21:37
加载中...