洛谷 P1725 简单DP单调队列优化

题意:起点为1,终点为n,每个点都有一个权值ai,每次只能从i走到[i+l, i+r],求能获得的最大权值

n <= 2e5

简单的dp,转移为dp[i] = max(dp[j]) + a[i],但是显然直接暴力会T

倒推,单调队列维护一下跑过的dp[i],更新前面的值

 

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<iostream>
 5 #include<deque>
 6 #define LL long long
 7 #define debug(x) cout << "[" << x << "]" << endl
 8 using namespace std;
 9 
10 const int mx = 2e5+10;
11 struct node{
12     int a, id;
13     node(int a = 0, int id = 0): a(a), id(id){}
14 };
15 deque<node> q;
16 int dp[mx], a[mx];
17 
18 int main(){
19     int n, l, r;
20     scanf("%d%d%d", &n, &l, &r);
21     for (int i = 0; i <= n; i++) scanf("%d", &a[i]);
22     for (int i = n-l+1; i <= n; i++) dp[i] = a[i];
23     for (int i = n+1; i >= l; i--){
24         while (!q.empty() && dp[i] > q.back().a) q.pop_back();
25         q.push_back(node(dp[i], i));
26         dp[i-l] = q.front().a+a[i-l];
27         if (i+r == q.front().id) q.pop_front();
28     }
29     printf("%d\n", dp[0]);
30     return 0;
31 }

 

posted @ 2018-08-25 21:10  QAQorz  阅读(273)  评论(0编辑  收藏  举报