P3810 【模板】三维偏序(陌上花开)重糊

重糊带师

我们之前的做法是cdq套cdq,但是这个做法复杂度虽然正确常数爆炸爆炸qwq

所以我们这里用树状数组写了一遍

首先我们要保证用a第一维排序,然后b和c是第二第三关键字去排序

然后cdq归并排序去保证b哪一位左边小于右边

再用树状数组保证左边小于右边

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define mid ((l+r)>>1)
using std::sort;
const int MAXN=2e5+7;
int n,qwq,tag[MAXN];
struct NODE {
	int a,b,c,ans,cnt;
	bool operator<(const NODE &x)const {
//		return a<x.a;
		if(a==x.a) {
			if(b==x.b)return c<x.c;
			else return b<x.b;
		} else return a<x.a;
	}
} node[MAXN],b[MAXN],que[MAXN],a[MAXN];

namespace seg {
#define lowbit(x) (x&(-x))
	int tr[MAXN];
	inline void add(int x,int val) {
		for(; x<MAXN; x+=lowbit(x)) {
			tr[x]+=val;
		}
	}
	inline int qry(int x) {
		int ret=0;
		for(; x; x-=lowbit(x)) {
			ret+=tr[x];
		}
		return ret;
	}
}
using namespace seg;

inline void solve(int l,int r) {
	if(l==r)return ;
	solve(l,mid);
	solve(mid+1,r);
//	sort(node+l,node+mid+1,cmp);
//	sort(node+mid+1,node+r,cmp);
//	printf("%d %d %d\n",l,mid,r);
	int cnt=0;
	for(int i=l,j=l,k=mid+1; i<=r; ++i) {
		if((k>r||node[j].b<=node[k].b)&&(j<=mid)) {
//			printf("?%d %d %d %d\n",node[j].id,node[j].a,node[j].b,node[j].c);
			add(node[j].c,node[j].cnt);
			que[++cnt]=node[j];
			b[i]=node[j];
			++j;

		} else {
//			printf("!%d %d %d %d->",node[k].id,node[k].a,node[k].b,node[k].c);
			int tmp=qry(node[k].c);
			node[k].ans+=tmp;
//			printf("%d\n",tmp);
			b[i]=node[k];
			++k;
		}
	}
//	puts("QWQ");
	for(int i=1; i<=cnt; ++i) {
//		printf("%dQWQ %d ",que[i].c,que[i].cnt);
		add(que[i].c,-que[i].cnt);
	}
//	printf("\n\n");
	for(int i=l; i<=r; ++i) {
//		if(i<=tmp) {
//		printf(")%d %d %d %d\n",node[i].id,node[i].a,node[i].b,node[i].c);
//			add(node[i].c,-1);
//		}
		node[i]=b[i];
	}
	return ;
}

int main() {
	scanf("%d%d",&n,&qwq);
	for(int i=1; i<=n; ++i) {
		scanf("%d%d%d",&a[i].a,&a[i].b,&a[i].c);
//		a[i].id=i;
	}
	sort(a+1,a+n+1);
	int top=0;
	int rc=0;
	for(int i=1; i<=n; ++i) {
		top++;
		if(a[i+1].a!=a[i].a||a[i+1].b!=a[i].b||a[i+1].c!=a[i].c) {
			node[++rc]=a[i];
			node[rc].cnt=top;
			top=0;
		}
	}
	solve(1,rc);
	for(int i=1; i<=rc; ++i) {
		tag[node[i].ans+node[i].cnt-1]+=node[i].cnt;
//		printf("%d\n",ans[i]);
	}
	for(int i=0; i<n; ++i) {
		printf("%d\n",tag[i]);
	}
	return 0;
}