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
const int N = 2e5;
#define

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;
}