欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

BZOJ 3262 陌上花开 三维偏序,CDQ分治

程序员文章站 2022-05-14 18:53:39
...
題意:长度为n的三元组序列(a,b,c), 对每个i询问有多少个j满足 ai>=aj && bi>=bj && ci>=cj.
n,a,b,c<=1e5.
第一维排序,然后对序列分治.

每次分治后对第二维进行归并,归并时考虑左区间对右区间的贡献,BIT维护第三维.O(n*logn*logn)

#include <bits/stdc++.h>
using namespace std;
const int N=2e5+5;
struct node{
	int x,y,z,cnt,ans;
}a[N],b[N];
bool cmp(node a,node b){
	if(a.x==b.x){
		if(a.y==b.y)	return a.z<b.z;
		return a.y<b.y;
	}
	return a.x<b.x;
}
int n,m,k,c[N],res[N];
bool cmp1(node a,node b){
	if(a.y==b.y)	return a.z<b.z;
	return a.y<b.y;
}
int lowbit(int x){return x&-x;}
void update(int x,int val){
	for(int i=x;i<N;i+=lowbit(i))	c[i]+=val;
}
int query(int x){
	int res=0;
	for(int i=x;i>0;i-=lowbit(i))	res+=c[i];
	return res;
}
void cdq(int l,int r)
{
	if(l==r)	return;
	int mid=l+r>>1;
	cdq(l,mid),cdq(mid+1,r);
	sort(b+l,b+1+mid,cmp1),sort(b+mid+1,b+1+r,cmp1);
	int i=l,j=mid+1;
	while(j<=r)
	{
		while(i<=mid&&b[i].y<=b[j].y)	update(b[i].z,b[i].cnt),i++;
		b[j].ans+=query(b[j].z);
		j++;
	}
	for(int p=l;p<i;p++)	update(b[p].z,-b[p].cnt);
}
int main()
{
//	ios::sync_with_stdio(false);
//	cin.tie(0);
	cin>>n>>k;
	for(int i=1;i<=n;i++)
		cin>>a[i].x>>a[i].y>>a[i].z;	
	sort(a+1,a+1+n,cmp);
	int cnt=0;
	for(int i=1;i<=n;i++)
	{
		cnt++;
		if(a[i].x==a[i+1].x&&a[i].y==a[i+1].y&&a[i].z==a[i+1].z)	continue;
		else
		{
			b[++m]=a[i];
			b[m].cnt=cnt;
			cnt=0;
		}
	}
	cdq(1,m);
	for(int i=1;i<=m;i++)
		res[b[i].ans+b[i].cnt]+=b[i].cnt;	
	for(int i=1;i<=n;i++)
		cout<<res[i]<<'\n';
	return 0;
 }