将元素分为两类,大于
m
m
m
的和小于等于
m
m
m
的。
对于大于
m
m
m
的,我们将最大的那个放在序列末端,然后枚举其它元素有多少个能产生贡献,假设有
x
x
x
个能产生贡献,那么这
x
x
x
个元素还会消耗
x
d
xd
x
d
个其它(包括小于等于
m
m
m
的)元素,如果
x
(
d
+
1
)
+
1
>
n
x(d+1)+1>n
x
(
d
+
1
)
+
1
>
n
,那么这种枚举不成立,否则的话我们可以快速计算出当前情况下的最大值。
不过需要注意的是,最大的那个不一定会放在序列末端,事实上我们有时候大于
m
m
m
的元素无法被消耗完,这时候可以往队列末端放(所以假设有
g
g
g
个大于
m
m
m
的元素,当
g
>
x
(
d
+
1
)
+
1
g>x(d+1)+1
g
>
x
(
d
+
1
)
+
1
的时候的
c
a
s
e
case
c
a
s
e
也是需要被考虑的),其实放多了(大于
d
d
d
个)其实也没关系,因为这样算出来的一定不是最优解,后面算出最优解会将它替换掉。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e5+5;
ll a[maxn],b[maxn];
ll tota,totb;
int main(){
ll n,m,d;
scanf("%lld%lld%lld",&n,&d,&m);
for(int i=1;i<=n;++i){
int u;
scanf("%d",&u);
if(u>m)b[++totb]=u;
else a[++tota]=u;
}
sort(b+1,b+1+totb);
sort(a+1,a+1+tota);
for(int i=1;i<=totb;++i)b[i]+=b[i-1];
for(int i=1;i<=tota;++i)a[i]+=a[i-1];
if(!totb)printf("%lld\n",a[tota]);
else{
ll ans=0;
for(int i=totb;i>=1;--i){
if((totb-i)*(d+1)+1>n)continue;
ans=max(ans,b[totb]-b[i-1]+a[tota]-a[max((totb-i)*d-i+1,0ll)]);
}
printf("%lld\n",ans);
}
}