题意:有n支队伍一共参加了三场比赛。一支队伍x认为自己比另一支队伍y强当且仅当x在至少一场比赛中比y的排名高。求有多少组(x,y),使得x自己觉得比y强,y自己也觉得比x强(既互相觉得比对方强),(x, y), (y, x)算一组。
思路:当x自己觉得比y强,y自己也觉得比x强,只有这二种情况,第一种是x二场比y弱,一场比y强,第二种是x二场比y强,一场比y弱。无论哪一种都会产生二组逆序对,所以我们对第一场降序排序,对第二和第三场求逆序对(既已遍历中比当前值小的数目,可以树状数组维护,遍历一个,对值位置加一),再对第二场排序,对第三场对逆序对(同理)。最终对答案除二即可。
代码:
#include<bits/stdc++.h> #define ll long long #define inf 1024523 using namespace std; inline int read() { int x=0,f=1; char ch=getchar(); while(ch<'0'||ch>'9') { if(ch=='-') f=-1; ch=getchar(); } while(ch>='0'&&ch<='9') { x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); } return x*f; } int n, b[500005], c[500005]; struct w { int x, y, z; } w[200005]; bool cmp(struct w a,struct w b) { return a.x>b.x; } bool cmp1(struct w a,struct w b) { return a.y>b.y; } ll z=0; void add(int x,int k) { while(x<=n) { b[x]+=k; x+=(x&(-x)); } } ll sum(int x) { ll s=0; while(x>0) { s=s+b[x]; x-=(x&(-x)); } return s; } void add1(int x,int k) { while(x<=n) { c[x]+=k; x+=(x&(-x)); } } ll sum1(int x) { ll s=0; while(x>0) { s=s+c[x]; x-=(x&(-x)); } return s; } int main() { scanf("%d",&n); for(int i=0; i<n; i++) { scanf("%d%d%d",&w[i].x,&w[i].y,&w[i].z); } sort(w,w+n,cmp); memset(b,0,sizeof(b)); memset(c,0,sizeof(c)); for(int i=0; i<n; i++) { z+=sum(w[i].y); add(w[i].y,1); z+=sum1(w[i].z); add1(w[i].z,1); } memset(c,0,sizeof(c)); sort(w,w+n,cmp1); for(int i=0; i<n; i++) { z+=sum1(w[i].z); add1(w[i].z,1); } cout << z/2 << endl; return 0; }