琪露諾(洛谷P1725)(簡單滑窗優化Dp)
阿新 • • 發佈:2018-12-13
文章目錄
題目
非常廢話 傳送門
題目大意:
給你一個長度為n+1的格子,編號為[0,n],你在0,現在你要從0跳過n,每次你能跳到下一個格子的區間為[i+L,i+R],每個格子有一個價值A[i],求跳過n後使沿途格子價值和最大的最大值.
資料範圍
對於60%的資料: 對於100%的資料: 對於所有資料 且
思路
首先,我們可以非常容易地寫出: 但是這是一個的Dp,對於這道題只能過部分分,於是我們就要往優化方面去想了。 我們發現,對於一個狀態f[i]的f[j]所處的區間[i-R,i-L],是隨我們i增大而不斷向右一移動的,那我們就可以利用這一性質來進行滑窗,我們視窗的寬度是固定的,用優先佇列儲存狀態時,只要頂部與i的距離大於(R-L+1)就說明無法轉移,彈出就是了 這樣之後複雜度就是了
程式碼
#include<set>
#include<map>
#include<ctime>
#include<queue>
#include<cmath>
#include<cstdio>
#include<vector>
#include<climits>
#include<cstring>
#include<iostream>
#include<algorithm>
#define LL long long
using namespace std;
int read(){
int f=1,x=0;char s=getchar();
while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}
return x*f;
}
#define MAXN 200000
#define INF 0x3f3f3f3f
struct node{
int p,val;
friend bool operator < (node a,node b){return a.val<b.val;}
};
int a[MAXN+5],f[MAXN+5];
priority_queue<node> Q;
int main(){
int n=read(),L=read(),R=read();
for(int i=0;i<=n;i++)
a[i]=read();
for(int i=L;i<=n;i++){
Q.push((node){i-L,f[i-L]});
while(Q.top().p<i-R) Q.pop();
f[i]=Q.top().val+a[i];
}
int ans=-INF;
for(int i=n+1-R;i<=n;i++)
ans=max(ans,f[i]);
printf("%d\n",ans);
return 0;
}