【题意概述】
给出三个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 ",1LL*n*(n-1)/2-ans/2),0; }