CSP-S 2025 T1 [社团招新]解题报告

OI生涯之殇

场上被这道题硬控2h,最后只能打完性质分和暴力分仓皇离场
我的OI生涯的最后一场比赛就这么以一种极度恶心的方式落幕了

切入

我们首先要注意到$ n\geq 10^5$,这意味着 \(dp\)是不可行的,因此,我们要考虑贪心

解决

根据约束条件$ cnt_i \leq n/2$我们可以想到先贪心地取每个组的最大值,如果该方案合法,就输出结果
那如果不合法呢?
此时我们就要考虑反悔
可以用三个数组存每组次大值与最大值的差值,再快排一下,这样就可以在超出 \(n/2\)的组上对原有的 \(ans\)进行一个减法,直到该组合法
由于约束条件为 \(cnt_i \leq n/2\),我们可以推断出最多只有一个组是不合法的,故而能够证明这样的反悔是合法的
复杂度是很显然的$ O(n)$
为什么考场上我就没有想出来呢......

AC Code
#include<bits/stdc++.h>
#define int long long
#define endl '\n'
#define endll " "
#define fre(x) freopen(x".in","r",stdin);freopen(x".out","w",stdout);
#define pii pair<int,int>
#define pb push_back
#define eb emplace_back
#define it inline int
#define iv inline void
#define ib inline bool
#define sakura_no_uta return 0
#pragma GCC optimize(0)
#pragma GCC optimize(2)
#pragma GCC optimize(3,"Ofast","inline")
using namespace std;
const int MAXN=500050;
const int INF=0x3f3f3f3f3f3f3f3f;
const int MOD=998244353;
it gcd(int x,int y) {return y==0?x:gcd(y,x%y);}
it lcm(int x,int y) {return y/gcd(x,y)*x;}
it max(int x,int y) {return x>y?x:y;}
it min(int x,int y) {return x<y?x:y;}
it ksm(int x,int m,int mod)
{
	int res=1,bas=x%mod;
	while(m)
	{
		if(m&1)
			res=(res*bas)%mod;
		bas=(bas*bas)%mod;
		m >>= 1;
	}
	return res;
}
int n,m,l,r,u,v,w,cnt,tot,ans,cnt1,cnt2,cnt3,lim,T;
struct lane
{
	int a,b,c,maxn;
}t[MAXN];
int f[MAXN],g[MAXN],h[MAXN];
ib cmp(int x,int y)
{
	return x<y;
}
signed main()
{
	fre("club");
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	cin >> T;
	while(T--)
	{
		cin >> n;
		memset(t,0,sizeof(t));
		memset(f,0,sizeof(f));
		memset(g,0,sizeof(g));
		memset(h,0,sizeof(h));
		ans=0;
		cnt1=0;
		cnt2=0;
		cnt3=0;
		lim=n/2;
		for(int i=1;i<=n;i++)
		{
			cin >> t[i].a >> t[i].b >> t[i].c;
			t[i].maxn=max(t[i].a,max(t[i].b,t[i].c));
			if(t[i].a==t[i].maxn)
			{
				ans+=t[i].maxn;
				f[++cnt1]=max(t[i].b-t[i].a,t[i].c-t[i].a);
			}
			else
			{
				if(t[i].b==t[i].maxn)
				{
					ans+=t[i].maxn;
					g[++cnt2]=max(t[i].a-t[i].b,t[i].a-t[i].b);
				}
				else
				{
					ans+=t[i].maxn;
					h[++cnt3]=max(t[i].a-t[i].c,t[i].b-t[i].c);
				}
			}
		}
		sort(f+1,f+cnt1+1,cmp);
		sort(g+1,g+cnt2+1,cmp);
		sort(h+1,h+cnt3+1,cmp);
		while(cnt1>lim)
			ans+=f[cnt1--];
		while(cnt2>lim)
			ans+=g[cnt2--];
		while(cnt3>lim)
			ans+=h[cnt3--];
		cout<<ans<<endl;
	}
	sakura_no_uta;
}
posted @ 2025-11-05 22:02  KLaneX  阅读(34)  评论(0)    收藏  举报