0
点赞
收藏
分享

微信扫一扫

Contest【树状数组+逆序对】

Contest【树状数组+逆序对】

牛客NC13947

题目描述

n支队伍一共参加了三场比赛。

一支队伍x认为自己比另一支队伍y强当且仅当x在至少一场比赛中比y的排名高。

求有多少组(x,y),使得x自己觉得比y强,y自己也觉得比x强。

(x, y), (y, x)算一组。

输入描述

第一行一个整数n,表示队伍数; 接下来n行,每行三个整数a[i], b[i], c[i],分别表示i在第一场、第二场和第三场比赛中的名次;n 最大不超过200000

输出描述

输出一个整数表示满足条件的(x,y)数;64bit请用lld

#include<bits/stdc++.h>
using namespace std;

#define int long long
const int N = 2e5;
#define pii pair<int,int>

int a[4][N + 5];    //第1,2,3列分别表示第一、二、三场的排名
int n,all,tree[N + 5];
pii p[N + 5];       //将两场比赛的数据存储到pair当中

void update(int x){ //更新树状数组
    for(;x <= n;x += x & -x)
        tree[x] += 1;
}
int get_sum(int x){ //查询前缀和
    int ans = 0;
    for(;x;x -= x & -x)
        ans += tree[x];
    return ans;
}

signed main(){
    cin>>n;
    for(int i = 1;i <= n;++i)
        cin>>a[1][i]>>a[2][i]>>a[3][i];
    for(int i = 1;i < 3;++i)
        for(int j = i + 1;j <= 3;++j){
            memset(tree,0,sizeof(tree));
            for(int k = 1;k <= n;++k)
                p[k].first = a[i][k],p[k].second = a[j][k];
            sort(p + 1,p + n + 1);
            for(int k = 1;k <= n;++k){
                update(p[k].second);
                all += k - get_sum(p[k].second);
            }
        }
    cout<<all / 2;
        //两个队伍的排名关系只有两种
        // 一个队伍每次都比另一个队伍靠前、一个队伍两次比另一个队伍靠前
        //这样的话,这两个队伍的逆序数情况就是0或2,但是这两个队伍对多只有算一对
        //所以除以2:0/2=0,2/2=1
    return 0;
}
举报

相关推荐

0 条评论