NKOJ P1654 [东方幻想乡] 琪露诺【单调队列优化DP】

看到有人居然有人说不会写 D P 这道题,然后写了一个分块 O r z O r z

f [ i ] 表示考虑前 i 个石头可以得到的最大值,所以一个很显然的方程:

f [ i ] = m a x   f [ j ] + a [ i ] , i R i i L

然后我们用单调队列维护一个递减序列即可。

#include <deque>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define DB double
#define SG string
using namespace std;
const int Max=3e5;
deque<int>DQ;
int N,L,R,A[Max],DP[Max];
inline int Read(){
    int X=0;char CH=getchar();bool F=0;
    while(CH>'9'||CH<'0'){if(CH=='-')F=1;CH=getchar();}
    while(CH>='0'&&CH<='9'){X=(X<<1)+(X<<3)+CH-'0';CH=getchar();}
    return F?-X:X;
}
inline void Write(int X){
    if(X<0)X=-X,putchar('-');
    if(X>9)Write(X/10);
    putchar(X%10+48);
}
int main(){
    int I,J,K;
    N=Read();L=Read(),R=Read();
    for(I=0;I<=N;I++){
        A[I]=Read();
    }
    DQ.push_back(0);
    for(I=L;I<=N+R;I++){
        while(DQ.size()!=0&&DP[DQ.back()]<=DP[I-L]){
            DQ.pop_back();
        }
        DQ.push_back(I-L);
        while(DQ.size()!=0&&DQ.front()<I-R){
            DQ.pop_front();
        }
        DP[I]=DP[DQ.front()]+A[I]; 
    }
    Write(DP[N+R]);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/yanzhenhuai/article/details/81557622
今日推荐