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;
}

浙公网安备 33010602011771号