Contest (树状数组求逆序对)

Posted blowhail

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Contest (树状数组求逆序对)相关的知识,希望对你有一定的参考价值。

 

题目链接:https://ac.nowcoder.com/acm/problem/13947

题目大意:有n个队伍参加三场比赛,如果队伍x有一场比赛赢了队伍y,y也有一场比赛赢了x,就算一组,求有多少组。

思路:这里我用了树状数组求逆序对的方法,先对第一场比赛进行排序,然后求第二场和第三场的逆序对,之后再对第二场比赛进行排序,求第三场比赛的逆序对,最后再除个2即可。详细的过程写到注释里了。

 

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <string>
#include <stack>
#include <queue>
#include <cmath>
#define ll long long
#define pi 3.1415927
#define inf 0x3f3f3f3f
#define mod 1000000007
using namespace std;
int n,a[200005],c[200005];
struct node{
    int x,y,z;
}tr[200005];
bool rankx (node x ,node y) ///对第一场比赛排序
{
    return x.x<y.x;
}
bool ranky (node x,node y) ///对第二场比赛排序
{
    return x.y<y.y;
}

int lowbit(int i)
{
    return i&-i;
}
void add(int i, int k) 
{
    while(i<=n)
    {
        c[i]+=k;
        i+=lowbit(i);
    }
}
int getsum(int i)
{
    int sum=0;
    while(i>0)
    {
        sum+=c[i];
        i-=lowbit(i);
    }
    return sum;
}

int main ()
{
    int m,i,t,j,k,p=1;
    ll sum=0;
    cin>>n;
    for(i=1;i<=n;++i)
        scanf("%d %d %d",&tr[i].x,&tr[i].y,&tr[i].z);
    ///第一次先对第一场比赛排序
    sort(tr+1,tr+n+1,rankx);
    for(i=1;i<=n;++i){
        add(tr[i].y,1);
        sum+=i-getsum(tr[i].y);  ///求第二场的逆序对
    }
    memset(c,0,sizeof(c)); ///重置一下
    for(i=1;i<=n;++i){
        add(tr[i].z,1);
        sum+=i-getsum(tr[i].z);///再求第三场的逆序对
    }
    ///按照第二场比赛排序,然后求第三场的逆序对
    sort(tr+1,tr+n+1,ranky);
    memset(c,0,sizeof(c));
    for(i=1;i<=n;++i){
        add(tr[i].z,1);
        sum+=i-getsum(tr[i].z); 
    }

    cout<<sum/2<<endl;

    return 0;
}

 

以上是关于Contest (树状数组求逆序对)的主要内容,如果未能解决你的问题,请参考以下文章

Asia Yokohama Regional Contest 2018 G题 What Goes Up Must Come Down(树状数组求逆序对)

树状数组求逆序对

树状数组求逆序对

求逆序数(树状数组+离散化)

树状数组求逆序对

HDU 1394 Minimum Inversion Number (树状数组求逆序对)