21.7.13 t2
tag:wqs二分
这个 \(k\) 长得一脸wqs二分的样子,实际上确实也是wqs二分。
如果给每个物品都加上一个 \(dlt\),那么 \(dlt\) 越大,选的数就越多。
所以就二分这个 \(dlt\) 了。
然后 dp 可以 \(O(n)\) 解决。
- \(f[i]+a_i\to f[i+m]\)
- \(f[i]\to f[i+1]\)
#pragma GCC optimize("Ofast")
#include<bits/stdc++.h>
using namespace std;
template<typename T>
inline void Read(T &n){
char ch; bool flag=false;
while(!isdigit(ch=getchar()))if(ch=='-')flag=true;
for(n=ch^48;isdigit(ch=getchar());n=(n<<1)+(n<<3)+(ch^48));
if(flag)n=-n;
}
typedef long long ll;
#define ll __int128
enum{
MAXN = 2000005
};
int n, m, k;
ll a[MAXN];
inline void mmn(int &a, int b){a = max(a,b);}
ll f[MAXN];
int g[MAXN];
inline void check(ll dlt){
memset(f,0xcf,sizeof f);
memset(g,0x3f,sizeof g);
f[1] = 0; g[1] = 0;
for(int i=1; i<=n; i++) a[i] -= dlt;
for(int i=1; i<=n; i++){
if(f[i]+a[i] > f[min(n+1,i+m)])
f[min(n+1,i+m)] = f[i]+a[i],
g[min(n+1,i+m)] = g[i]+1;
else if(f[i]+a[i] == f[min(n+1,i+m)])
mmn(g[min(n+1,i+m)],g[i]);
if(f[i] > f[i+1])
f[i+1] = f[i],
g[i+1] = g[i];
else if(f[i] == f[i+1])
mmn(g[i+1],g[i]);
}
for(int i=1; i<=n; i++) a[i] += dlt;
// printf("%d ",g[n+1]);
}
template<typename T>
void print(T n){
if(n>9) print(n/10);
putchar(n%10+'0');
}
int main(){
// freopen("2.in","r",stdin);
// freopen("22.out","w",stdout);
Read(n); Read(m); Read(k);
ll sum=0;
for(int i=1; i<=n; i++) Read(a[i]), sum += a[i];
ll head = -sum, tail = sum;
while(head<tail){
ll mid = head+tail >> 1; check(mid);
if(g[n+1] >= k) head = mid+1;
else tail = mid;
}
head--;
check(head);
print(f[n+1]+k*head);puts("");
return 0;
}