BZOJ4430: [Nwerc2015]Guessing Camels赌骆驼

Posted ONION_CYC

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ4430: [Nwerc2015]Guessing Camels赌骆驼相关的知识,希望对你有一定的参考价值。

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

【算法】逆序对

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

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

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

技术分享
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cctype>
#define lowbit(x) x&-x
#define ll long long
using 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<b.num;}
void modify(int x){for(int i=x;i<=n;i+=lowbit(i))d[i]++;}
int query(int x){int ans=0;for(int i=x;i>=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

 

以上是关于BZOJ4430: [Nwerc2015]Guessing Camels赌骆驼的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ4430: [Nwerc2015]Guessing Camels赌骆驼

bzoj 4428: [Nwerc2015]Debugging调试

BZOJ4428[Nwerc2015]Debugging调试 记忆化搜索+分块

BZOJ4429[Nwerc2015] Elementary Math小学数学 最大流

[bzoj4429] [Nwerc2015] Elementary Math小学数学

bzoj4428[Nwerc2015]Debugging调试 数论+记忆化搜索