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;
} 
京公网安备 11010502036488号