树状数组+排序

A比B的一场排名高,并且B也有一场的排名比A高
那么对第一场排序后,就保证了后面的排名比前面的排名高,这样只需要统计有多少个数对(a[i],a[j]) 满足 i<j && a[i]>a[j] 这不就是求逆序数对吗。
所以我们对任意两场求逆序数对即可。
以第一场排序后,求相对于第一场而言,第二场的逆序数对(即求出第一场、第二场之间的满足的),第三场的逆序数对(即求出第一场、第三场之间的满足的)
然后在以第二场排序,求相对于第二场而言,第三场的逆序数对(即求出第二场、第三场之间的满足的)
最后的结果要除以2,为什么?假设存在一组逆序数对,假设A的第一场比B的第一场高,A的第二场比B的第二场低,这已经满足了,考虑第三组的高低情况,因为排名不会一样,所以对于满足的而言,必定是一个队伍比另一个队伍两高一低/一高两低的情况,这样就重复计算了一次。
比如
2
1 2 2
2 1 1
容易得到第一场排序后,第二场的逆序数对有1,第三场的逆序数对有1,
第二场排序后,第三场的逆序数对为0.
但是答案是1,并不是1+1+0=2

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=2e5+5;
struct node{int a,b,c;}q[maxn];
int c[maxn];
void add(int x){
    for(;x<maxn;x+=x&(-x)) c[x]++;
}
ll get_sum(int x){
    ll sum=0;
    for(;x;x-=x&(-x)) sum+=c[x];
    return sum;
}
int main(){
    //ios::sync_with_stdio(0);
    int n;scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%d%d%d",&q[i].a,&q[i].b,&q[i].c);
    sort(q+1,q+1+n,[](node a,node b){
       return a.a<b.a; 
    });
    ll sum=0;
    for(int i=1;i<=n;i++) add(q[i].b),sum+=i-get_sum(q[i].b);
    memset(c,0,sizeof c);
    for(int i=1;i<=n;i++) add(q[i].c),sum+=i-get_sum(q[i].c);
    memset(c,0,sizeof c);
    sort(q+1,q+1+n,[](node a,node b){
           return a.b<b.b; 
    });
    for(int i=1;i<=n;i++) add(q[i].c),sum+=i-get_sum(q[i].c);
    printf("%lld",sum/2);
    return 0;
}