P9525 [JOISC 2022 Day2] 团队竞技 题解
来发一个简单的 \(O(n \log n)\) 做法。
考虑如果没有要求三只海狸每一只都要有特长,那么我们就会贪心的选择 \(x_i\) 最大的、\(y_i\) 最大的和 \(z_i\) 最大的。
考虑如果答案不是这样,那么必然有一只海狸同时满足 \(x_i\) 最大、\(y_i\) 最大、\(z_i\) 最大当中的至少两项,注意到这只海狸不可能存在于答案之中。
我们将这只海狸从序列中删除,那么问题变为了原来的一个子问题,而我们要求的东西不变。
具体过程用三个堆或者 set 维护一下最大值即可,知道最后可以选取 \(x_i,y_i,z_i\) 三者最大值作为答案再停止。
代码如下。
#include<bits/stdc++.h>
#define fi first
#define se second
#define mk make_pair
using namespace std;
const int MAXN = 2e5+5;
int n;
int x[MAXN], y[MAXN], z[MAXN];
bool mark[MAXN];
set<pair<int,int> > A, B, C;
int main(){
ios::sync_with_stdio(0);
cin >> n; pair<int,int> now; int a, b, c;
for(int i=1;i<=n;++i) cin >> x[i] >> y[i] >> z[i], A.insert(mk(x[i],i)), B.insert(mk(y[i],i)), C.insert(mk(z[i],i));
while(A.size() && B.size() && C.size()){
now=*A.rbegin();
if(mark[now.se]){
A.erase(*A.rbegin());
continue;
}
a=now.fi;
now=*B.rbegin();
if(mark[now.se]){
B.erase(*B.rbegin());
continue;
}
b=now.fi;
now=*C.rbegin();
if(mark[now.se]){
C.erase(*C.rbegin());
continue;
}
c=now.fi;
now=*A.rbegin();
if(y[now.se]>=b){
mark[now.se]=1;
A.erase(*A.rbegin());
continue;
}
if(z[now.se]>=c){
mark[now.se]=1;
A.erase(*A.rbegin());
continue;
}
now=*B.rbegin();
if(x[now.se]>=a){
mark[now.se]=1;
B.erase(*B.rbegin());
continue;
}
if(z[now.se]>=c){
mark[now.se]=1;
B.erase(*B.rbegin());
continue;
}
now=*C.rbegin();
if(x[now.se]>=a){
mark[now.se]=1;
C.erase(*C.rbegin());
continue;
}
if(y[now.se]>=b){
mark[now.se]=1;
C.erase(*C.rbegin());
continue;
}
break;
}
if(A.size()==0 || B.size()==0 || C.size()==0) cout << -1;
else cout << (*A.rbegin()).fi+(*B.rbegin()).fi+(*C.rbegin()).fi;
return 0;
}

浙公网安备 33010602011771号