D. Boboniu Chats with Du
原题链接:
https://codeforces.ml/contest/1395/problem/D
题目大意:
在qq聊天中Du有$n$句话,每句话有不同的数值,一天只能说一句话,如果高于$m$的话就会在之后被禁言$d$天。要求出Du可以得到的最大值。
解题思路:
将$n$句话分成两部分,一部分是小于m的,另一部分是大于m的。首先将这两部分分别排序(从大到小),然后计算前缀和。接着可以枚举说的话小于m的个数i,如果$(n- i )%(d + 1)$则可以取$(n- i )/(d + 1)$,否则可以取$(n- i )/(d + 1)+1$个。然后求出最大值即可。
代码:
1 #include <bits/stdc++.h>
2 using namespace std;
3 typedef long long ll;
4 typedef pair<ll,ll> pi;
5 typedef complex <double> cp;
6 #define debug(a) cout<<#a<<":"<<a<<endl;
7 #define fr freopen("in.txt","r",stdin);
8 #define Fill(x,a) memset(x,a,sizeof(x))
9 #define cpy(a,b) memcpy(a,b,sizeof(a))
10 const double PI = acos(-1);
11 const ll INF=0x3f3f3f3f;
12 const ll N=1e6+7;
13 const ll mod=1e9+7;
14 ll maxn,minn;
15 ll T,n,m,q,d;
16 ll a[N];
17 ll b[N];
18 ll arr[N];
19 ll aa,bb;
20 ll dpa[N];
21 ll dpb[N];
22
23 int main(){
24 cin>>n>>d>>m;
25 aa=bb=0;
26 for(ll i=1;i<=n;i++){
27 scanf("%lld",arr+i);
28 if(arr[i]>m){
29 b[++bb]=arr[i];
30 }
31 else{
32 a[++aa]=arr[i];
33 }
34 }
35 sort(a+1,a+aa+1);
36 sort(b+1,b+bb+1);
37 reverse(a+1,a+aa+1);
38 reverse(b+1,b+bb+1);
39 maxn=0;
40 Fill(dpa,0);
41 Fill(dpb,0);
42 for(ll i=1;i<=n;i++){
43 dpa[i]=dpa[i-1]+a[i];
44 }
45 for(ll i=1;i<=n;i++){
46 dpb[i]=dpb[i-1]+b[i];
47 }
48 for(ll i=0;i<=aa;i++){
49 int j;
50 if((n-i)%(d+1)==0){
51 j=(n-i)/(d+1);
52 }
53 else{
54 j=(n-i)/(d+1)+1;
55 }
56 maxn=max(maxn,dpa[i]+dpb[j]);
57 }
58 cout<<maxn<<endl;
59
60 return 0;
61 }
62
63