bzoj 3831 Little Bird (单调队列优化dp)

/*先贴个n*n的*/
#include<iostream>
#include<cstdio>
#include<cstring>
#define maxn 1000010
using namespace std;
int n,k,h[maxn],f[maxn],Q;
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
      scanf("%d",&h[i]);
    scanf("%d",&Q);
    while(Q--)
      {
          scanf("%d",&k);
          memset(f,127/3,sizeof(f));
          f[1]=0;
          for(int i=1;i<=n;i++)
            for(int j=i-k;j<i;j++)
              {
                if(j<=0)continue;
              if(h[i]>=h[j])f[i]=min(f[i],f[j]+1);
              if(h[i]<h[j])f[i]=min(f[i],f[j]);
            }
        printf("%d
",f[n]);
      }
    return 0;
}
/*
对于每次的查找最小值 用单调队列维护 
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#define maxn 1000010
using namespace std;
int n,k,h[maxn],f[maxn],Q,q[maxn],head,tail;
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
      scanf("%d",&h[i]);
    scanf("%d",&Q);
    while(Q--)
      {
          head=1;tail=0;
          scanf("%d",&k);
          f[1]=0;q[++tail]=1;
          for(int i=2;i<=n;i++)
            {
            while(tail>=head&&i-q[head]>k)head++;
                if(h[i]>=h[q[head]])f[i]=f[q[head]]+1;
                else f[i]=f[q[head]];
                while(head<=tail&&f[i]<=f[q[tail]])
              {
                  if(f[i]==f[q[tail]]&&h[i]<h[q[tail]])break;
                  tail--;
              }
                q[++tail]=i;
          }
        printf("%d
",f[n]);
      }
    return 0;
}
原文地址:https://www.cnblogs.com/yanlifneg/p/5704676.html