题目链接: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; }