Contest
题目
题目描述
\(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)\) 数;\(64\) bit请用lld
示例1
输入
4
1 3 1
2 2 4
4 1 2
3 4 3
输出
5
题解
知识点:分治,排序。
这是一道多维偏序题,可以CDQ分治,但鄙人还不会,这里用逆序对的。
注意到,一对的三场比赛至少一强一弱,由于\((x, y), (y, x)\)算一组,因此在计算一场比赛时只管弱或者强的一种可能就行,另一种可能是重复的。
我们对第一场比赛排序,使得 \(i<j\) 时 \(i\) 比 \(j\) 弱。现在去找第二场的逆序对,得到的答案便是第一场弱第二场强的对,但第三场不定;再对第一场排序,找第三场的逆序数,就找到了第一场弱第三场强的对,但第二场不定;再对第二场排序,找第三场的逆序数,就找到了第二场弱第三场强的对,但第一场不定。
于是我们得到了 \(6\) 组情况(1代表强,0代表弱):
序号/场次 | 第一场 | 第二场 | 第三场 |
---|---|---|---|
1 | 0 | 1 | 1 |
2 | 0 | 1 | 0 |
3 | 0 | 1 | 1 |
4 | 0 | 0 | 1 |
5 | 1 | 0 | 1 |
6 | 0 | 0 | 1 |
我们发现 \(1\) 和 \(3\) 重复了,\(4\) 和 \(6\) 重复了。\(2\) 和 \(5\) 是互反的,由于每个组都是一种情况的全部可能性,而两种情况互反算一组,所以重复了。因此最终答案是三种情况相加除以 \(2\) 。
时间复杂度 \(O(n\log n)\)
空间复杂度 \(O(n)\)
代码
#include <bits/stdc++.h>
using namespace std;
struct team {
int a, b, c;
}P[200007];
int Q[200007], R[200007];
long long ans = 0;
void merge_sort(int l, int r) {
if (l == r) return;
int mid = l + r >> 1;
merge_sort(l, mid);
merge_sort(mid + 1, r);
int i = l, j = mid + 1, k = l;
while (i <= mid && j <= r) {
if (Q[i] <= Q[j]) R[k++] = Q[i++];
else R[k++] = Q[j++], ans += mid - i + 1;
}
while (i <= mid) R[k++] = Q[i++];
while (j <= r)R[k++] = Q[j++];
for (int i = l;i <= r;i++) Q[i] = R[i];
}
int main() {
std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int n;
cin >> n;
for (int i = 0;i < n;i++) cin >> P[i].a >> P[i].b >> P[i].c;
sort(P, P + n, [&](team a, team b) {return a.a < b.a;});
for (int i = 0;i < n;i++) Q[i] = P[i].b;
merge_sort(0, n - 1);
for (int i = 0;i < n;i++) Q[i] = P[i].c;
merge_sort(0, n - 1);
sort(P, P + n, [&](team a, team b) {return a.b < b.b;});
for (int i = 0;i < n;i++) Q[i] = P[i].c;
merge_sort(0, n - 1);
cout << ans / 2 << '\n';
return 0;
}
本文来自博客园,作者:空白菌,转载请注明原文链接:https://www.cnblogs.com/BlankYang/p/16407138.html