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;
}
posted @ 2024-02-08 19:58  OccDreamer  阅读(24)  评论(0)    收藏  举报