【容斥原理】【推导】【树状数组】Gym - 101485G - Guessing Camels

题意:给你三个1~n的排列a,b,c,问你在 (i,j)(1<=i<=n,1<=j<=n,i≠j),有多少个有序实数对(i,j)满足在三个排列中,i都在j的前面。

暴力求的话是三维偏序,相对比较困难。但是我们可以用一些简单的方法。

设在a中i在j前面的有序实数对数为A,b中为B,c中为C。(其实显然A=B=C=n*(n-1)/2)

要求的即为A∩B∩C。

利用容斥原理A+B+C-A∩B-A∩C-B∩C+A∩B∩C=A∪B∪C ①,以及Ω-A∪B∪C=A∩B∩C ②可容易求得。(显然Ω=n*(n-1))

②式怎么来的呢?显然,在三个序列中均满足i在j前面的有序实数对(i,j),必然与在三个序列中都未出现的有序实数对(j,i)一一对应,证毕。

而A∩B、A∩C、B∩C都可以通过二维偏序(排序+树状数组)求得。

所以最后答案就是(n*(n-1)-(n*(n-1)/2*3-A∩B-A∩C-B∩C))/2。

#include
#include
#include
using namespace std;
typedef long long ll;
int n;
int d[200005];
void Update(int p){for(;p<=n;p+=(p&(-p))) ++d[p];}
int Query(int p){int res=0; for(;p;p-=(p&(-p))) res+=d[p]; return res;}
ll A[3];
struct data{
	int x,y;
	data(const int &x,const int &y){
		this->x=x;
		this->y=y;
	}
	data(){}
}a[200005],b[200005],c[200005],p[3][200005];
bool operator < (const data &a,const data &b){
	return a.x

转载于:https://www.cnblogs.com/autsky-jadek/p/7700491.html

你可能感兴趣的:(【容斥原理】【推导】【树状数组】Gym - 101485G - Guessing Camels)