Codeforces 1077 F2. Pictures with Kittens (hard version) dp
阿新 • • 發佈:2020-09-10
題解
- 首先考慮直接$dp$的寫法$dp_{i,j,k}$表示在前$i$個數選擇了$j$個數後末尾連續未選擇的數個數為$k$可取得的最大值,轉移也很簡單。
- 但這個做法是$O(n^3)$的,觀察一下可以發現$k$這一維可以用單調佇列優化掉,然後複雜度就為$O(n^2)$
檢視程式碼
#include <bits/stdc++.h> using namespace std; #define _for(i,a,b) for(int i = (a);i <= (b);++i) typedef long long ll; const int maxn = 5000+5; const int mod = 1e9+7; ll qpow(ll a,ll b){ll res = 1;for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;} int que[maxn][maxn]; int top[maxn],tail[maxn]; int a[maxn]; ll dp[maxn][maxn]; int main() { #ifndef ONLINE_JUDGE freopen("simple.in","r",stdin); freopen("simple.out","w",stdout); #endif int n,m,k; cin>>n>>m>>k; for(int i = 1;i <= n;++i)scanf("%d",&a[i]); que[k][0] = 0; tail[k] = 1; memset(dp,-0x3f,sizeof(dp)); dp[0][k]=0; ll ans = -1; for(int i = 1;i <= n;++i){ for(int j = 0;j < k;++j){ int &s = top[j+1]; int &t = tail[j+1]; while(s!=t&&i-que[j+1][s]>=m+1){ s++; } if(s!=t) dp[i][j] = dp[que[j+1][s]][j+1]+a[i]; int &s2 = top[j],&t2 = tail[j]; while(s2!=t2&&dp[i][j]>=dp[que[j][t2-1]][j]){ t2--; } que[j][t2++] = i; if(j==0&&n-i<m){ ans = max(ans,dp[i][j]); } } } cout<<ans<<endl; return 0; }