Codeforces Round #521 (Div. 3): F. Pictures with Kittens(DP+單調佇列)
阿新 • • 發佈:2018-11-23
題意:
你有n幅畫,第i幅畫的好看程度為ai,再給你兩個數字k,x,表示你要從中選出剛好x幅畫,並且相鄰兩幅畫的距離不能≥k,好看程度之和最大能多少,選不出來輸出-1,F1資料範圍<200,F2資料範圍<5000
注意相鄰兩幅畫的距離不能≥k指的是中間沒有選的畫個數不能≥k,而不是絕對值之差≥k
思路:
dp[x][y]表示只考慮前y幅畫,第y幅必選,且總共選了x幅畫的最大好看程度
轉移:dp[x][y] = max(dp[x-1][y-k]~dp[x-1][y-1])+a[y]
然後這個DP很明顯可以用單調佇列維護
#include<stdio.h> #include<string.h> #include<algorithm> #include<map> #include<string> #include<math.h> #include<queue> #include<stack> #include<iostream> using namespace std; #define LL long long #define mod 1000000007 LL a[5005], dp[2][5005]; int st[5005]; int main(void) { LL ans; int n, k, m, i, p, R, L, now; scanf("%d%d%d", &n, &m, &k); for(i=1;i<=n;i++) scanf("%lld", &a[i]); memset(dp, -62, sizeof(dp)); dp[0][0] = 0, now = 1; for(p=1;p<=k;p++) { L = 1, R = 0; st[++R] = 0; for(i=1;i<=n;i++) { while(R>=L && st[L]+m<i) L++; dp[now][i] = dp[now^1][st[L]]+a[i]; while(R>=L && dp[now^1][st[R]]<=dp[now^1][i]) R--; st[++R] = i; } now ^= 1; } now ^= 1, ans = -1; for(i=n;i>=n-m+1;i--) ans = max(ans, dp[now][i]); printf("%lld\n", ans); return 0; }