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

题目链接

本人博客

前言

恩对,笔者在考场上思来想去,一共实现了 \(3\) 种代码,但无一例外,均未调出来。怒得 \(25\) pts遗憾退场。

思路

首先需要让每个人选自己最喜欢的社团(贪心),这无疑是最优的。但是有可能不合法。

那我们考虑不合法应该怎么办。

\(3\) 个部门人数为 \(a,b,c\)(其中 \(a \geq b \geq c\))。如果不合法当且仅当 \(a > \frac{n}{2}\)\(b,c < \frac{n}{2}\)。证明如下。

| 由题意可知 \(a + b + c = n\)。若 \(a > \frac{n}{2}\),则为 \(n-(b+c) > \frac{n}{2}\),即 \(b+c < \frac{n}{2}\)

因此只需要考虑其中一个部门不合法的情况。(笔者就是这个证明考场上脑子不好使,没想到)

于是只需要预处理每个人从他最喜欢的部门到他次喜欢的部门的满意度差。答案把多出来的人的差减去即可。

笔者这里用的是优先队列维护,时间复杂度 \(O(n \log n)\)

代码如下

#include<cstdio>
#include<iostream> 
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
#define int long long 
inline int Read(){
    int x=0,f=1;
    char c=getchar();
    while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
    while(isdigit(c)){x=x*10+c-48;c=getchar();}
    return x*f;
}
inline void Write(int x){
    if(x<0){x=-x;putchar('-');}
    if(x>9) Write(x/10);
    putchar(x%10+'0');
}
const int N=1e5+10;
int T,n,ans;
int a[10]; 
priority_queue<int> q1,q2,q3;
//三个队列用来维护每个部门的人数和每个人次大与最大之间的差
//注意默认为大根堆
int Max_3(int a,int b,int c){return max(max(a,b),c);}//最大值
void solve(){
    ans=0;
    while(!q1.empty()) q1.pop();
    while(!q2.empty()) q2.pop();
    while(!q3.empty()) q3.pop();
    //多测清空!
    n=Read();
    for(int i=1;i<=n;i++){//边输入边处理
        for(int j=1;j<=3;j++){
            a[j]=Read();
        } 
        int t=Max_3(a[1],a[2],a[3]);
        if(a[1]==t){
            ans+=a[1];
            q1.push(max(a[2]-a[1],a[3]-a[1]));
            //因为默认大根堆,而我们最后贪心出队的应该是差最小的,所以可以存复数,出队的时候直接加  
        }
        else if(a[2]==t){
            ans+=a[2];
            q2.push(max(a[1]-a[2],a[3]-a[2]));  
        }
        else if(a[3]==t){
            ans+=a[3];
            q3.push(max(a[1]-a[3],a[2]-a[3]));
        }
    }
    while(q1.size()>n/2){
        ans+=q1.top();q1.pop();
    }
    while(q2.size()>n/2){
        ans+=q2.top();q2.pop();
    }
    while(q3.size()>n/2){
        ans+=q3.top();q3.pop();
    }	
    printf("%lld\n",ans);
}
signed main(){
    T=Read();
    while(T--){
        solve();//多测函数好
    }
    return 0; 
}
posted on 2025-11-03 16:38  _Liuliuliuliuliu  阅读(5)  评论(0)    收藏  举报