[COGS2479]偏序

[COGS2479]偏序

题目大意:

\(n(n\le50000)\)个四元组,求四维偏序。

思路:

CDQ分治套CDQ分治套树状数组。

细节:

第二层CDQ之前要备份数组\(a\),否则第二层CDQ结束以后\(a\)就不对了。

源代码:

#include<cstdio>
#include<cctype>
#include<algorithm>
inline int getint() {
	register char ch;
	while(!isdigit(ch=getchar()));
	register int x=ch^'0';
	while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
	return x;
}
const int N=50001;
int n,ans;
struct Node {
	int id,x,y,z,type;
};
Node a[N],tmp[N];
inline bool cmp1(const Node &p1,const Node &p2) {
	return p1.x<p2.x;
}
inline bool cmp2(const Node &p1,const Node &p2) {
	return p1.y<p2.y;
}
class FenwickTree {
	private:
		int val[N];
		int lowbit(const int &x) const {
			return x&-x;
		}
	public:
		void modify(int p,const int &x) {
			for(;p<=n;p+=lowbit(p)) val[p]+=x;
		}
		int query(int p) const {
			int ret=0;
			for(;p;p-=lowbit(p)) ret+=val[p];
			return ret;
		}
};
FenwickTree t;
void cdq2(const int &b,const int &e) {
	if(b==e) return;
	const int mid=(b+e)>>1;
	cdq2(b,mid);
	cdq2(mid+1,e);
	int p=b,q=mid+1;
	for(;q<=e;q++) {
		if(a[q].type==1) continue;
		for(;p<=mid&&a[p].y<a[q].y;p++) {
			if(a[p].type==1) t.modify(a[p].z,1);
		}
		ans+=t.query(a[q].z);
	}
	while(--p>=b) {
		if(a[p].type==1) t.modify(a[p].z,-1);
	}
	std::inplace_merge(&a[b],&a[mid]+1,&a[e]+1,cmp2);
}
void cdq1(const int &b,const int &e) {
	if(b==e) return;
	const int mid=(b+e)>>1;
	cdq1(b,mid);
	cdq1(mid+1,e);
	for(register int i=b;i<=mid;i++) a[i].type=1;
	for(register int i=mid+1;i<=e;i++) a[i].type=2;
	std::inplace_merge(&a[b],&a[mid]+1,&a[e]+1,cmp1);
	std::copy(&a[b],&a[e]+1,&tmp[b]);
	cdq2(b,e);
	std::copy(&tmp[b],&tmp[e]+1,&a[b]);
}
int main() {
	freopen("partial_order.in","r",stdin);
	freopen("partial_order.out","w",stdout);
	n=getint();
	for(register int i=1;i<=n;i++) a[i].id=i;
	for(register int i=1;i<=n;i++) a[i].x=getint();
	for(register int i=1;i<=n;i++) a[i].y=getint();
	for(register int i=1;i<=n;i++) a[i].z=getint();
	cdq1(1,n);
	printf("%d\n",ans);
	return 0;
}
posted @ 2018-08-12 21:05  skylee03  阅读(186)  评论(0编辑  收藏  举报