【CJOJ2616】 【HZOI 2016】偏序 I(cdq分治,树状数组)

传送门

CJOJ

Solution

考虑这是一个四维偏序对吧。
直接cdq套在一起,然后这题有两种实现方法(树状数组的更快!)

代码实现1(cdq+cdq+cdq)

/*
  mail: mleautomaton@foxmail.com
  author: MLEAutoMaton
  This Code is made by MLEAutoMaton
*/
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<algorithm>
#include<queue>
#include<set>
#include<map>
#include<iostream>
using namespace std;
#define ll long long
#define re register
#define file(a) freopen(a".in","r",stdin);freopen(a".out","w",stdout)
inline int gi()
{
	int f=1,sum=0;char ch=getchar();
	while(ch>'9' || ch<'0'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0' && ch<='9'){sum=(sum<<3)+(sum<<1)+ch-'0';ch=getchar();}
	return f*sum;
}
const int N=100010;
struct node
{
	int a,b,c,opt1,opt2;
}a[N<<1],tmp1[N],tmp2[N],tmp3[N];
int n,ans;
void cdq3(int,int);
void cdq2(int,int);
void cdq1(int,int);
int main()
{
	n=gi();
	for(int i=1;i<=n;i++)a[i].a=gi();
	for(int i=1;i<=n;i++)a[i].b=gi();
	for(int i=1;i<=n;i++)a[i].c=gi();
	cdq1(1,n);
	printf("%d\n",ans);
	return 0;
}
void cdq1(int l,int r)
{
	if(l==r)return;
	int mid=(l+r)>>1;
	cdq1(l,mid);cdq1(mid+1,r);
	int tot=l-1;int L=l,R=mid+1;
	while(L<=mid && R<=r)
	{
		if(a[L].a<a[R].a){a[L].opt1=0;tmp1[++tot]=a[L++];}
		else{a[R].opt1=1;tmp1[++tot]=a[R++];}
	}
	while(L<=mid){a[L].opt1=0;tmp1[++tot]=a[L++];}
	while(R<=r){a[R].opt1=1;tmp1[++tot]=a[R++];}
	for(int i=l;i<=r;i++)a[i]=tmp1[i];
	cdq2(l,r);
}
void cdq2(int l,int r)
{
	if(l==r)return;
	int mid=(l+r)>>1;
	cdq2(l,mid);cdq2(mid+1,r);
	int tot=l-1;int L=l,R=mid+1;
	while(L<=mid && R<=r)
	{
		if(tmp1[L].b<tmp1[R].b){tmp1[L].opt2=0;tmp2[++tot]=tmp1[L++];}
		else{tmp1[R].opt2=1;tmp2[++tot]=tmp1[R++];}
	}
	while(L<=mid){tmp1[L].opt2=0;tmp2[++tot]=tmp1[L++];}
	while(R<=r){tmp1[R].opt2=1;tmp2[++tot]=tmp1[R++];}
	for(int i=l;i<=r;i++)tmp1[i]=tmp2[i];
	cdq3(l,r);
}
void cdq3(int l,int r)
{
	if(l==r)return;
	int mid=(l+r)>>1;
	cdq3(l,mid);cdq3(mid+1,r);
	int tot=l-1;int L=l,R=mid+1,cnt=0;
	while(L<=mid && R<=r)
	{
		if(tmp2[L].c<tmp2[R].c){if((tmp2[L].opt1|tmp2[L].opt2)==0)cnt++;tmp3[++tot]=tmp2[L++];}
		else{if((tmp2[R].opt1&tmp2[R].opt2)==1)ans+=cnt;tmp3[++tot]=tmp2[R++];}
	}
	while(R<=r){if((tmp2[R].opt1&tmp2[R].opt2)==1)ans+=cnt;tmp3[++tot]=tmp2[R++];}
	while(L<=mid)tmp3[++tot]=tmp2[L++];
	for(int i=l;i<=r;i++)tmp2[i]=tmp3[i];
}

代码实现2(cdq+cdq+BIT)

/*
  mail: mleautomaton@foxmail.com
  author: MLEAutoMaton
  This Code is made by MLEAutoMaton
*/
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<algorithm>
#include<queue>
#include<set>
#include<map>
#include<iostream>
using namespace std;
#define ll long long
#define re register
#define file(a) freopen(a".in","r",stdin);freopen(a".out","w",stdout)
inline int gi()
{
	int f=1,sum=0;char ch=getchar();
	while(ch>'9' || ch<'0'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0' && ch<='9'){sum=(sum<<3)+(sum<<1)+ch-'0';ch=getchar();}
	return f*sum;
}
const int N=100010;
struct node
{
	int a,b,c,opt;
}a[N<<1],tmp1[N],tmp2[N];
int n,tot,ans,c[N];
int lowbit(int x){return x&(-x);}
void Add(int x,int d){while(x<=n){c[x]+=d;x+=lowbit(x);}}
int query(int x){int ret=0;while(x){ret+=c[x];x-=lowbit(x);}return ret;}
void cdq2(int,int);
void cdq1(int,int);
int main()
{
	n=gi();
	for(int i=1;i<=n;i++)a[i].a=gi();
	for(int i=1;i<=n;i++)a[i].b=gi();
	for(int i=1;i<=n;i++)a[i].c=gi();
	cdq1(1,n);
	printf("%d\n",ans);
	return 0;
}
void cdq1(int l,int r)
{
	if(l==r)return;
	int mid=(l+r)>>1;
	cdq1(l,mid);cdq1(mid+1,r);
	tot=l-1;int L=l,R=mid+1;
	while(L<=mid && R<=r)
	{
		if(a[L].a<a[R].a){a[L].opt=0;tmp1[++tot]=a[L++];}
		else{a[R].opt=1;tmp1[++tot]=a[R++];}
	}
	while(L<=mid){a[L].opt=0;tmp1[++tot]=a[L++];}
	while(R<=r){a[R].opt=1;tmp1[++tot]=a[R++];}
	for(int i=l;i<=r;i++)a[i]=tmp1[i];
	cdq2(l,r);
}
void cdq2(int l,int r)
{
	if(l==r)return;
	int mid=(l+r)>>1;
	cdq2(l,mid);cdq2(mid+1,r);
	int L=l,R=mid+1;tot=0;
	while(L<=mid && R<=r)
	{
		if(tmp1[L].b<tmp1[R].b)
		{
			tmp2[++tot]=tmp1[L];
			if(!tmp1[L].opt)Add(tmp1[L].c,1);
			L++;
		}
		else
		{
			tmp2[++tot]=tmp1[R];
			if(tmp1[R].opt)ans+=query(tmp1[R].c);
			R++;
		}
	}
	while(R<=r)
	{
		tmp2[++tot]=tmp1[R];
		if(tmp1[R].opt)ans+=query(tmp1[R].c);
		R++;
	}
	for(int i=l;i<L;i++)if(!tmp1[i].opt)Add(tmp1[i].c,-1);
	while(L<=mid){tmp2[++tot]=tmp1[L];L++;}
	for(int i=l;i<=r;i++)tmp1[i]=tmp2[i-l+1];
}
posted @ 2019-03-21 22:21  QwQGJH  阅读(261)  评论(0编辑  收藏  举报