【BZOJ 3262】-陌上花开(CDQ分治+树状数组)

传送门

CDQ分治练习题

首先以第一维为关键字排序

然后这样就只剩两维了

就像常规的CDQCDQ分治一样

处理二维偏序关系就可以了

将满足第二维关系的的三维放在一个树状数组维护查询就可以了

#include<bits/stdc++.h>
using namespace std;
inline int read(){
	char ch=getchar();
	int res=0,f=1;
	while(!isdigit(ch)){if(ch=='-')f=-f;ch=getchar();}
	while(isdigit(ch))res=(res<<3)+(res<<1)+(ch^48),ch=getchar();
	return res*f;
} 
const int N=400005;
struct flw{
	int a,b,c,cnt,ans;
}a[N],p[N];
inline bool cmp(const flw &a,const flw &b){
	if(a.a==b.a&&a.b==b.b)return a.c<b.c;
	if(a.a==b.a)return a.b<b.b;
	return a.a<b.a;
}
inline bool comp(const flw &a,const flw &b){
	if(a.b==b.b)return a.c<b.c;
	return a.b<b.b;
}
int tr[N],n,m,tot,cnt,ans[N];
inline int lowbit(int x){return (x&(-x));}
inline void update(int pos,int k){for(;pos<=m;pos+=lowbit(pos))tr[pos]+=k;}
inline int query(int pos,int res=0){for(;pos;pos-=lowbit(pos))res+=tr[pos];return res;}
#define mid ((l+r)>>1)
inline void cdq(int l,int r){
	if(l==r)return;
	cdq(l,mid),cdq(mid+1,r);
	sort(a+l,a+mid+1,comp);
	sort(a+mid+1,a+r+1,comp);
	int i=l;
	for(int j=mid+1;j<=r;j++){
		while(i<=mid&&a[i].b<=a[j].b){
			update(a[i].c,a[i].cnt),i++;
		}
		a[j].ans+=query(a[j].c);
	}
	for(int j=l;j<i;j++)update(a[j].c,-a[j].cnt);
}
#undef mid
int main(){
	n=read(),m=read();
	for(int i=1;i<=n;i++){
		p[i].a=read(),p[i].b=read(),p[i].c=read();
	}
	sort(p+1,p+n+1,cmp);
	for(int i=1;i<=n;i++){
		cnt++;
		if(p[i].a!=p[i+1].a||p[i].b!=p[i+1].b||p[i].c!=p[i+1].c){
			a[++tot]=p[i],a[tot].cnt=cnt,cnt=0;
		}
	}
	cdq(1,tot);
	for(int i=1;i<=n;i++){
		ans[a[i].ans+a[i].cnt-1]+=a[i].cnt;
	}
	for(int i=0;i<n;i++){
		cout<<ans[i]<<"
";
	}
}
原文地址:https://www.cnblogs.com/stargazer-cyk/p/10366359.html