acm-(模拟、暴力枚举)Codeforces Round #664 (Div. 1) A. Boboniu Chats with Du

  • Post author:
  • Post category:其他


题面


传送门

将元素分为两类,大于



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



版权声明:本文为qq_30361651原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。