【LZU第四屆程式設計大賽】終極較量
阿新 • • 發佈:2020-11-23
Description
比賽很快就開始了,所有參賽的選手將在這裡展開一場全面的終極較量。
每一位選手都有三個屬性 \(A\)、\(B\)、\(C\),每個屬性都是一個正整數,
如果一個選手 \(X\) 有一個屬性的值大於另一個選手 \(Y\) 對應的屬性值,則認為 \(X\) 可以擊敗 \(Y\);
如果 \(X\) 能夠擊敗 \(Y\),\(Y\) 能夠擊敗 \(Z\),則認為 \(X\) 也能擊敗 \(Z\);
在一個選手能夠擊敗的人中,每個人統計且僅統計一次,請你幫 \(GJX\) 算一算,他能夠擊敗多少角色。
特別的,選手自己不能擊敗自己,即自己不會出現在自己擊敗的計數中。
Input
第一行,一個整數 \(n \ (1 \leq n \leq 2 \times 10^5)\),代表該遊戲中的所有玩家數;
第二行,\(3\) 個正整數(不超過 \(int\)),分別代表 \(GJX\) 的三個屬性值;
接下來的 \(n - 1\) 行,每行 \(3\) 個數,代表除了 \(GJX\) 以外的選手的三個屬性的值;
資料保證不會出現兩位選手的所有屬性值相同。
Output
一行,一個整數,代表 \(GJX\) 最多可以擊敗多少選手(不包括 \(GJX\) 自己)。
Sample Input 1
3
10 1 3
9 5 7
3 8 2
Sample Output 1
2
題解
考慮這樣的集合,集合之中的任意一人不會被集合之外的人打敗,
在保證 \(GJX\) 不在這樣的集合之中的前提下,最大化這個集合就能解決問題。
按照三個屬性值分別排序,然後從 \(1\) 到 \(n\) 依次考慮上述集合的大小,
把當前考慮到的大小,在按三個屬性值排序的陣列中涉及到的人統計下來,
如果涉及人數和當前考慮的大小一致,說明找到了一個這樣的集合;
需要注意的是,如果這期間在任意陣列遇到 \(GJX\) 都要停止。
AC程式碼
點選展開
#include <cstdio> #include <algorithm> using namespace std; inline int read() { int num = 0; char c = getchar(); while (c < '0' || c > '9') c = getchar(); while (c >= '0' && c <= '9') num = num * 10 + c - '0', c = getchar(); return num; } const int MAXN = 2e5 + 5; struct Person { int id, value; bool operator < (const Person &rhs) const { return value > rhs.value; } } a[MAXN], b[MAXN], c[MAXN]; int vis[MAXN]; int main() { int n = read(); for (int i = 1; i <= n; ++i) { a[i].id = i, a[i].value = read(); b[i].id = i, b[i].value = read(); c[i].id = i, c[i].value = read(); } sort(a + 1, a + n + 1); sort(b + 1, b + n + 1); sort(c + 1, c + n + 1); int ans = n - 1, num = 0, cnt = 0; for (int i = 1; i <= n; ++i) { if (a[i].id == 1 || b[i].id == 1 || c[i].id == 1) break; if (!vis[a[i].id]) ++cnt, vis[a[i].id] = 1; if (!vis[b[i].id]) ++cnt, vis[b[i].id] = 1; if (!vis[c[i].id]) ++cnt, vis[c[i].id] = 1; if (cnt == i - num) num += cnt, cnt = 0; } printf("%d", ans - num); return 0; }