博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【BZOJ】4430: [Nwerc2015]Guessing Camels赌骆驼
阅读量:6840 次
发布时间:2019-06-26

本文共 1314 字,大约阅读时间需要 4 分钟。

【题意】给定三个长度为n的排列,求在三个排列中顺序相同的数对个数。

【算法】逆序对

【题解】很容易联想到NOIP火柴排队,涉及顺序问题显然和逆序对息息相关。

一个数对如果在三个排列中顺序不同,一定是1+2或2+1,也就是只在两数列之间顺序相同。

所以对三个数列两两求逆序对总数num,则不满足要求的数对一定会产生且仅产生两个逆序对,ans=n*(n-1)/2-num/2。

#include
#include
#include
#include
#define lowbit(x) x&-x#define ll long longusing namespace std;int read(){ char c;int s=0,t=1; while(!isdigit(c=getchar()))if(c=='-')t=-1; do{s=s*10+c-'0';}while(isdigit(c=getchar())); return s*t;}const int maxn=200010;ll ans;int d[maxn],n,A[maxn];struct cyc{
int num,id;}a[maxn],b[maxn],c[maxn];bool cmp(cyc a,cyc b){
return a.num
=1;i-=lowbit(i))ans+=d[i];return ans;}void calc(cyc a[],cyc b[]){ memset(d,0,sizeof(d)); for(int i=1;i<=n;i++)A[a[i].id]=b[i].id; for(int i=1;i<=n;i++){ modify(A[i]); ans+=i-query(A[i]); }}int main(){ n=read(); for(int i=1;i<=n;i++)a[i].num=read(),a[i].id=i; for(int i=1;i<=n;i++)b[i].num=read(),b[i].id=i; for(int i=1;i<=n;i++)c[i].num=read(),c[i].id=i; sort(a+1,a+n+1,cmp);sort(b+1,b+n+1,cmp);sort(c+1,c+n+1,cmp); ans=0; calc(a,b);calc(b,c);calc(a,c); printf("%lld",1ll*n*(n-1)/2-ans/2); return 0;}
View Code

 

转载于:https://www.cnblogs.com/onioncyc/p/7782150.html

你可能感兴趣的文章