• 【BZOJ】4430: [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
  • 相关阅读:
    C语言寒假大作战01
    第十二次作业
    第十一次作业
    第十周作业
    第九次作业
    第8周作业
    第七次作业
    C语言I作业12—学期总结
    第一周作业
    C语言l博客作业02
  • 原文地址:https://www.cnblogs.com/onioncyc/p/7782150.html
Copyright © 2020-2023  润新知