1. 程式人生 > >BZOJ 4430 Guessing Camels賭駱駝

BZOJ 4430 Guessing Camels賭駱駝

const blog sizeof for light -1 getc string query

【題意概述】

給出三個n的排列,求有多少個數對在三個排列中順序相同

【題解】

考慮用補集轉化的方法,答案為總對數-不滿足的對數

一對數不滿足條件,當且僅當這對數在兩個排列中順序相同,在另一個排列中的順序不同。

統計兩兩之間不滿足偏序條件的數對的個數,那麽每對數都被統計了兩次

#include<cstdio>
#include<algorithm>
#include<cstring> 
#define LL long long
using namespace std;
const int maxn=200010;
int n,a[4][maxn],b[maxn],t[maxn];
LL ans,tmp;
void read(int &k){
	k=0; int f=1; char c=getchar();
	while(c<‘0‘||c>‘9‘)c==‘-‘&&(f=-1),c=getchar();
	while(‘0‘<=c&&c<=‘9‘)k=k*10+c-‘0‘,c=getchar();
	k*=f;
}
void add(int x){for(;x<=n;x+=(x&-x)) t[x]++;}
int query(int x){int ret=0; for(;x>0;x-=(x&-x)) ret+=t[x]; return ret;}
int main(){
	read(n); 
	for (int j=1;j<=3;j++)
		for (int i=1;i<=n;i++) read(a[j][i]);
	for (int i=1;i<3;i++)
	for (int j=i+1;j<=3;j++){
		memset(t,0,sizeof(t)); tmp=0;
		for (int k=1;k<=n;k++) b[a[i][k]]=k;
		for (int k=1;k<=n;k++) a[j][k]=b[a[j][k]];
		for (int k=1;k<=n;k++) tmp+=query(a[j][k]),add(a[j][k]);
		ans+=1LL*n*(n-1)/2-tmp;
	}
	return printf("%lld\n",1LL*n*(n-1)/2-ans/2),0;
}

  

BZOJ 4430 Guessing Camels賭駱駝