联考「联测缺颈(team)」题解

核心思路:有两项能力为当前全局最大值的人一定不会被选中。

考虑把所有的人分别按照三项能力排序,然后分别取出三项能力最强的三个人。如果有一个人没有特长,则把这个人踢掉,换下一个。

以上过程可以用排序维护,也可以用 std::multiset 维护。不过笔者试了很久都不成功,同时 std::multiset 时间复杂度比排序大,所以建议使用排序

代码

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include <bits/stdc++.h>
using namespace std;
int a[150005],b[150005],c[150005];
int ind1[150005],ind2[150005],ind3[150005];
int vis[150005];
int main() {
  int n;
  scanf("%d",&n);
  for(int i = 1;i <= n;i++) {
    scanf("%d%d%d",a + i,b + i,c + i);
    ind1[i] = ind2[i] = ind3[i] = i;
  }
  sort(ind1 + 1,ind1 + 1 + n,[](int i,int j){return a[i] < a[j];});
  sort(ind2 + 1,ind2 + 1 + n,[](int i,int j){return b[i] < b[j];});
  sort(ind3 + 1,ind3 + 1 + n,[](int i,int j){return c[i] < c[j];});
  int p1 = n,p2 = n,p3 = n,i = ind1[n],j = ind2[n],k = ind3[n];
  while(p1 && p2 && p3) {
    while(vis[i]) i = ind1[--p1];
    while(vis[j]) j = ind2[--p2];
    while(vis[k]) k = ind3[--p3];
    if(b[i] == b[j] || c[i] == c[k]) vis[i] = 1,i = ind1[--p1];
    else if(a[j] == a[i] || c[j] == c[k]) vis[j] = 1,j = ind2[--p2];
    else if(a[k] == a[i] || b[k] == b[j]) vis[k] = 1,k = ind3[--p3];
    else break;
  }
  if(p1 && p2 && p3) printf("%d\n",a[i] + b[j] + c[k]);
  else printf("-1\n");
  return 0;
}