BZOJ_3831_[Poi2014]Little Bird_Monotonic queue optimization DP

BZOJ_3831_[Poi2014]Little Bird_Monotonic queue optimization DP

Description

There is a row of n trees, and the height of the ith tree is Di.
MHY is going to play with his sister from the first tree to the nth tree.
If MHY is in the ith tree, then he can jump to the i+1,i+2,...,i+kth tree.
If MHY jumps to a tree that is not shorter than the current tree, his effort value will be +1, otherwise not.
In order to have physical strength to play with girls, MHY should minimize the fatigue value.

Input

There is a single integer N(2<=N<=1 000 000) in the first line of the standard input: the number of trees in the Byteotian Line Forest. The second line of input holds   integers D1,D2…Dn(1<=Di<=10^9) separated by single spaces: Di is the height of the i-th tree.
The third line of the input holds a single integer Q(1<=Q<=25): the number of birds whose flights need to be planned. The following Q lines describe these birds: in the i-th of these lines, there is an integer Ki(1<=Ki<=N-1) specifying the i-th bird's stamina. In other words, the maximum number of trees that the i-th bird can pass before it has to rest is Ki-1.

Output

Your program should print exactly Q lines to the standard output. In the I-th line, it should specify the minimum number of tiresome flight legs of the i-th bird.

Sample Input

9
4 6 3 6 3 7 2 6 5
2
2
5

Sample Output

2
1

First there is the DP equation F[i]=min(F[j]+(d[i]>=d[j])) (1<=ij<=k)

It can be found that as a decision point, the smaller F value is better (because it only adds at most 1 each time), and the higher F value is better.

The DP process can then be optimized with monotonic queues.

When comparing decision points who are more preferred, compare F first, and then compare height.

 

Code:

#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
#define N 1000500
int f[N],d[N],n,m,Q[N],l,r;
bool check(int j,int k) {
    if(f[j]==f[k]) return d[k]>d[j];
    return f[k]<f[j];
}
int main() {
    scanf("%d",&n);
    int i,k;
    for(i=1;i<=n;i++) {
        scanf("%d",&d[i]);
    }
    scanf("%d",&m);
    while(m--) {
        scanf("%d",&k);
        l=r=0;
        f[1]=0;Q[r++]=1;
        for(i=2;i<=n;i++) {
            while(l<r&&i-Q[l]>k) l++;
            f[i]=f[Q[l]]+(d[i]>=d[Q[l]]);
            while(l<r&&check(Q[r-1],i)) r--;
            Q[r++]=i;
        }
        printf("%d\n",f[n]);
    }
}

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325353328&siteId=291194637