牛客练习赛2 A - Contest
链接:https://www.nowcoder.com/acm/contest/4/A
来源:牛客网
题目描述
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
示例1
输入
4 1 3 1 2 2 4 4 1 2 3 4 3
输出
5
题解
三维偏序,$cdq$分治。
总的方案数有$n*(n - 1) / 2$种,不满足条件的就是三维偏序,减去即可。
#include<bits/stdc++.h> using namespace std; const int maxn = 2e5 + 10; struct X { int a, b, c; int id; }s[maxn]; int n; int f[maxn]; int c[maxn]; int lowbit(int x) { return x & (-x); } void update(int p, int v) { for(int i = p; i < maxn; i = i + lowbit(i)) { c[i] += v; } } int sum(int p) { int res = 0; while(p) { res += c[p]; p -= lowbit(p); } return res; } bool cmpA(const X& a, const X& b) { return a.a < b.a; } bool cmpB(const X& a, const X& b) { return a.b < b.b; } bool cmpID(const X& a, const X& b) { return a.id < b.id; } void cdq(int L, int R) { if(L == R) return; int mid = (L + R) / 2; sort(s + L, s + mid + 1, cmpB); sort(s + mid + 1, s + R + 1, cmpB); int p1 = L; for(int i = mid + 1; i <= R; i ++) { while(p1 <= mid && s[p1].b <= s[i].b) { update(s[p1].c, 1); p1 ++; } f[s[i].id] += sum(s[i].c); } for(int i = L; i < p1; i ++) { update(s[i].c, -1); } sort(s + L, s + mid + 1, cmpID); sort(s + mid + 1, s + R + 1, cmpID); cdq(L, mid); cdq(mid + 1, R); } int main() { scanf("%d", &n); for(int i = 1; i <= n; i ++) { scanf("%d%d%d", &s[i].a, &s[i].b, &s[i].c); } sort(s + 1, s + 1 + n, cmpA); for(int i = 1; i <= n; i ++) { s[i].id = i; // printf("%d %d %d %d\n", s[i].a, s[i].b, s[i].c, s[i].id); } cdq(1, n); long long A = 1LL * n; long long B = 1LL * (n - 1); long long C = 0; if(A % 2 == 0) A = A / 2; else B = B / 2; for(int i = 1; i <= n; i ++) { C = C + 1LL * f[i]; } printf("%lld\n", A * B - C); return 0; }