传送门
题目大意:给n个数,限定d和m,求一个顺序使得序列和最大,当ai>m时,ai后d个数变为0,n范围1e5,其他1e9
思路:枚举+贪心
将数分为两组——大于m,小于等于m
分别排序和求好前缀和后,枚举大于m的数的数量i,有个小细节,最后一个地方方一个大于m的数更优(只占一格空间), 所占总空间为 1+(i-1)*(d+1),剩下空间塞满小于m的数即可,当i==0时,答案即为所有小于m的数的和,可以先将ans赋值为所有小于m的数的和
#include <iostream>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cstring>
#include <vector>
#include <map>
#include <queue>
using namespace std;
#define IOS ios::sync_with_stdio(false);cin.tie(0)
#define _for(i,a,b) for(int i=(a) ;i<=(b) ;i++)
#define _rep(i,a,b) for(int i=(a) ;i>=(b) ;i--)
#define mst(x,y) memset(x,y,sizeof(x))
#define all(v) v.begin() , v.end()
#define pb(v) push_back(v)
#define INF 0x3f3f3f3f
#define int long long
#define lson p*2,l,mid
#define rson p*2+1,mid+1,r
typedef long long ll;
const int N = 1e6+10;
int n,d,m;
int a[N],b[N],sum1[N],sum2[N];
int cnt1,cnt2;
bool cmp(int x,int y)
{
return x>y;
}
void solve()
{
sort(a+1,a+1+cnt1,cmp);
sort(b+1,b+1+cnt2,cmp);
_for(i,1,cnt1) sum1[i] = sum1[i-1] + a[i];
_for(i,1,n) sum2[i] = sum2[i-1] + b[i];
int ans=sum2[n];
for(int i=1 ;i<=cnt1 ;i++)
{
int temp = (i-1)*(d+1)+1;//占的空间
if( temp > n ) break;
int t = sum1[i] + sum2[n-temp];
ans = max(ans , t);
}
cout<<ans<<endl;
}
signed main()
{
//!!!!!!!!!!!!!!!!!!!!!!
// freopen("data.txt","r",stdin);
//!!!!!!!!!!!!!!!!!!!!!!
IOS;
cin>>n>>d>>m;
_for(i,1,n)
{
int x;
cin>>x;
if( x<=m ) b[++cnt2]=x;
else a[++cnt1]=x;
}
solve();
}