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\n",f[n]); } }