跳到主要内容
原文170 词数1 分钟

题解:P17831 [CSP-S 2026] 能量水晶

概述

水晶只能增加能量,同组元素升到组内最大值时操作最少。排序后只需考虑连续区间,利用区间和计算代价,并维护当前前缀的最优长度。每加入一个元素,只尝试将长度增加一;可行则增长,否则左端右移一次,保持原长度。最终窗口长度即为答案,总时间为 O(nlogn)。

解题思路​

将 aa 升序排序,最优选择可取为连续区间 [l,r][l,r],代价为:

∑i=lr(ar−ai)=(r−l+1)ar−∑i=lrai\sum_{i=l}^r(a_r-a_i)=(r-l+1)a_r-\sum_{i=l}^r a_i

维护前缀最优长度 kk。加入 ara_r 后,只可能改进为 k+1k+1,因此只检查末尾 k+1k+1 项。可行则增长,否则左端右移 11,维持长度;窗口本身允许暂不合法。最终长度即答案。

总时间复杂度 O(nlog⁡n)O(n\log n)。

参考代码​

368 Bcpp
#include <bits/stdc++.h>
using namespace std;

using ll=long long;
const int N=500005;
ll a[N];
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n;
ll m;
cin>>n>>m;
for(int i=1;i<=n;i++)cin>>a[i];
sort(a+1,a+n+1);
int l=1;
ll sum=0;
for(int i=1;i<=n;i++)
{
sum+=a[i];
if(a[i]*(i-l+1)-sum>m)sum-=a[l++];
}
cout<<n-l+1<<'\n';
return 0;
}