BZOJ 3831 单调队列DP

思路:

这好像是我刚学单调性的时候做的题

(我是不会告诉你 我被这题教做人了的...)

i-stk[head]>k 删队头
f[stk[tail]]>f[i]||(f[stk[tail]]==f[i]&&a[stk[tail]]<=a[i])删队尾


//By SiriusRen
#include <cstdio>
using namespace std;
int n,q,k,a[1000050],f[1000050],stk[1000050];
int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++)scanf("%d",&a[i]);
    scanf("%d",&q);
    while(q--){
        scanf("%d",&k);
        stk[1]=1;
        int head=1,tail=1;
        for(int i=2;i<=n;i++){
            while(head<=tail&&i-stk[head]>k)head++;
            f[i]=f[stk[head]]+(a[stk[head]]<=a[i]);
            while(head<=tail&&(f[stk[tail]]>f[i]||(f[stk[tail]]==f[i]&&a[stk[tail]]<=a[i])))tail--;
            stk[++tail]=i;
        }
        printf("%d
",f[n]);
    }
}
原文地址:https://www.cnblogs.com/SiriusRen/p/6592648.html