Description
n支队伍一共参加了三场比赛。
一支队伍x认为自己比另一支队伍y强当且仅当x在至少一场比赛中比y的排名高。
求有多少组(x,y),使得x自己觉得比y强,y自己也觉得比x强。
(x, y), (y, x)算一组。
Solution
容斥思想, 不考虑任何限制,总共有 种组合
我们要求题目给的限制方案不好求,逆向思维求不符合的情况
显然不符合的情况是一个三维偏序
三维偏序问题可以用 cdq 分治去解决,这里就不赘述了
得到三维偏序的方案为
那么答案就是
#include<iostream> #include<algorithm> using namespace std; struct node { int x, y, z; bool operator < (const node &s) { return x < s.x; } }a[200005], b[200005]; long long p; long long t[200005]; int lowbit(int x) { return x & (-x); } void add(int x, int y) { while(x < 200005) { t[x] += y; x += lowbit(x); } } long long sum(int x) { long long ans = 0; while(x) { ans += t[x]; x -= lowbit(x); } return ans; } void cdq(int l, int r) { if(l == r) return ; int mid = l + r >> 1; cdq(l, mid); cdq(mid + 1, r); int L = l, R = mid + 1, tot = l; while (L <= mid && R <= r) { if (a[L].y <= a[R].y) add(a[L].z, 1), b[tot++] = a[L++]; else p -= sum(a[R].z), b[tot++] = a[R++]; } while (L <= mid) { add(a[L].z, 1); b[tot++] = a[L++]; } while (R <= r) { p -= sum(a[R].z); b[tot++] = a[R++]; } for(int i = l; i <= mid; i++) add(a[i].z, -1); for(int i = l; i <= r; i++) a[i] = b[i]; } int main() { int n; cin >> n; for(int i = 1; i <= n; i++) { cin >> a[i].x >> a[i].y >> a[i].z; } p = 1LL * n * (n - 1) / 2; sort(a + 1, a + 1 + n); cdq(1, n); cout << p << "\n"; return 0; }