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;
}
posted @ 2021-07-13 15:08  oisdoaiu  阅读(24)  评论(0编辑  收藏  举报