题目大意:有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;
}
京公网安备 11010502036488号