专栏文章

[CSP-S 2025] 社团招新 / club

P14361题解参与者 27已保存评论 28

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
28 条
当前快照
1 份
快照标识符
@minfn14o
此快照首次捕获于
2025/12/02 01:38
3 个月前
此快照最后确认于
2025/12/02 01:38
3 个月前
查看原文

前言

我是不是赢在这个题 11 分钟秒了?这是不是矛盾的病句。

题目分析

首先默认全选满意度最大的社团,如果合法肯定就是答案,这一定最优。
考虑不合法,对人最多的社团移走一些人即可。由于要移到 n2\frac{n}{2} 人为止一定最优,不需要考虑因此其他集合元素超出限制的情况。可以预处理每个人到她次喜欢的社团的满意度差。直接排序贪心选最小的即可。
时间复杂度 O(nlogn)O(n\log n),好像可以用桶做到 O(n)O(n)

代码

CPP
#include<bits/stdc++.h>
#define ALL(x) x.begin(),x.end()
using namespace std;
constexpr int N=1e5+1;
int T,n,a[N][4],maxv,ans;
vector<int>members[4];
void Main(){
	for(int i=1;i<=3;i++)
		members[i].clear();
	ans=0;
	cin>>n;
	for(int i=1,x,y;i<=n;i++){
		cin>>a[i][1]>>a[i][2]>>a[i][3];
		if(a[i][1]>=a[i][2]&&a[i][1]>=a[i][3]){
			x=1,
			y=(a[i][2]>a[i][3]?2:3);
		}
		else if(a[i][2]>=a[i][1]&&a[i][2]>=a[i][3]){
			x=2,
			y=(a[i][1]>a[i][3]?1:3);
		}
		else{
			x=3,
			y=(a[i][1]>a[i][2]?1:2);
		}
		members[x].push_back(a[i][x]-a[i][y]);
		ans+=a[i][x];
	}
	if((maxv=max({members[1].size(),members[2].size(),members[3].size()}))<=n/2)
		cout<<ans<<'\n';
	else{
		int x=(members[1].size()==maxv?1:(members[2].size()==maxv?2:3)),rem=members[x].size()-(n/2);
		sort(ALL(members[x]));
		for(int i=0;i<rem;i++)
			ans-=members[x][i];
		cout<<ans<<'\n';
	}
	return;
}
int main(){
	ios::sync_with_stdio(0);
	cin.tie(nullptr),cout.tie(nullptr);
	for(cin>>T;T;--T)
		Main();
	return 0;
}

评论

28 条评论,欢迎与作者交流。

正在加载评论...