[luogu]P3572 [POI2014]PTA-Little Bird(单调队列)

P3572 [POI2014]PTA-Little Bird

题目描述

In the Byteotian Line Forest there are nn trees in a row.

On top of the first one, there is a little bird who would like to fly over to the top of the last tree.

Being in fact very little, the bird might lack the strength to fly there without any stop.

If the bird is sitting on top of the tree no. i, then in a single flight leg it can fly toany of the trees no. i+1,i+2,\cdots,i+ki+1,i+2,?,i+k, and then has to rest afterward.

Moreover, flying up is far harder to flying down. A flight leg is tiresome if it ends in a tree at leastas high as the one where is started. Otherwise the flight leg is not tiresome.

The goal is to select the trees on which the little bird will land so that the overall flight is leasttiresome, i.e., it has the minimum number of tiresome legs.

We note that birds are social creatures, and our bird has a few bird-friends who would also like to getfrom the first tree to the last one. The stamina of all the birds varies,so the bird‘s friends may have different values of the parameter kk.

Help all the birds, little and big!

从1开始,跳到比当前矮的不消耗体力,否则消耗一点体力,每次询问有一个步伐限制,求每次最少耗费多少体力

输入输出格式

输入格式:

There is a single integer nn (2\le n\le 1?000?0002≤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 nn integers d_1,d_2,\cdots,d_nd1?,d2?,?,dn? (1\le d_i\le 10^91≤di?≤109)separated by single spaces: d_idi? is the height of the i-th tree.

The third line of the input holds a single integer qq (1\le q\le 251≤q≤25): the number of birds whoseflights need to be planned.

The following qq lines describe these birds: in the ii-th of these lines, there is an integer k_iki? (1\le k_i\le n-11≤ki?≤n?1) specifying the ii-th bird‘s stamina. In other words, the maximum number of trees that the ii-th bird can pass before it has to rest is k_i-1ki??1.

输出格式:

Your program should print exactly qq lines to the standard output.

In the ii-th line, it should specify the minimum number of tiresome flight legs of the ii-th bird.

输入输出样例

输入样例#1: 复制

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

输出样例#1: 复制

2
1

说明

从1开始,跳到比当前矮的不消耗体力,否则消耗一点体力,每次询问有一个步伐限制,求每次最少耗费多少体力

题解

单调队列优化dp的经典题吧
先上\(O(n^2)\)方程
\(F[i]=min(F[j]+(h[j]<=h[i]));\)
很显然我们用贪心的思想。
对于 \(F[i]\) 来说,从越小的 \(F[j]\) 跳过来越好。
对于 \(h[i]\) 来说,在单调队列里面留下越大的 \(h[j]\) 越好
同时, \(F[i]\) 的单调性显然要优先于 \(h[i]\) 的单调性。
用单调队列维护两个单调性即可
以上\((j<i)\)

Code

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<cmath>
using namespace std;
const int N=1e6+5;
int m,f[N],k,n,ch[N],q[N];
int read(){
    int x=0,w=1;char ch=getchar();
    while(ch>'9'||ch<'0'){if(ch=='-')w=-1;ch=getchar();}
    while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
    return x*w;
}

bool cmp(int x,int y){
    return f[x]==f[y]?ch[x]>ch[y]:f[x]<f[y];
}

void solve(){
    k=read();
    memset(f,127/3,sizeof(f));f[1]=0;//ch[0]=1e9+1;
    int h=1,t=1;q[1]=1;
    for(int i=2;i<=n;i++){
        /*for(int j=max(0,i-k);j<i;j++){
        f[i]=min(f[i],f[j]+(ch[j]<=ch[i]));
        cout<<i<<' '<<f[i]<<endl;*/
        while(h<=t&&q[h]<i-k)h++;
        f[i]=f[q[h]]+(ch[q[h]]<=ch[i]);
        while(h<=t&&cmp(i,q[t]))t--;
        q[++t]=i;
    }
    cout<<f[n]<<endl;
}

int main(){
    n=read();
    for(int i=1;i<=n;i++)ch[i]=read();
    m=read();
    while(m--)solve();
    return 0;
}

原文地址:https://www.cnblogs.com/hhh1109/p/10667077.html

时间: 2024-08-01 20:30:55

[luogu]P3572 [POI2014]PTA-Little Bird(单调队列)的相关文章

【BZOJ3831】[Poi2014]Little Bird 单调队列

[BZOJ3831][Poi2014]Little Bird Description In the Byteotian Line Forest there are   trees in a row. On top of the first one, there is a little bird who would like to fly over to the top of the last tree. Being in fact very little, the bird might lack

BZOJ 3831 POI 2014 Little Bird 单调队列DP

题目大意:给出一片树林,树排成一排,每一棵树都有一个高度.从地一棵树出发,每次可以跳到i+k棵之前,跳到小于自己高度的树上不需要花费体力,反之需要花费一点体力,问到最后一棵树最少需要多少体力. 思路:简单DP方程:f[i] = min{f[j] + (height[i] >= height[j])} 然后发现数据范围只有O(n)可以过. 维护单调队列,队列中按照f单调递减,队尾按照时间往出弹. 当f值相同的时候,高度较高的优先. CODE: #include <queue> #inclu

bzoj3831 [Poi2014]Little Bird 单调队列优化dp

3831: [Poi2014]Little Bird Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 505  Solved: 322[Submit][Status][Discuss] Description In the Byteotian Line Forest there are   trees in a row. On top of the first one, there is a little bird who would like t

【单调队列】【动态规划】bzoj3831 [Poi2014]Little Bird

f(i)=min{f(j)+(D(j)<=D(i))} (max(1,i-k)<=j<=i) 有两个变量,很难用单调队列,但是(引用): 如果fi<fj,i一定比j优秀.因为如果heighti≥heightj就不用说了,如果heighti<heightj,i可以花1的代价跳到高的地方,顶多和j一样,不会比j差. 如果fi=fj,那当然就是谁的height高谁优秀. 双关键字搞一下就好了. #include<cstdio> using namespace std;

P3572 [POI2014]PTA-Little Bird

P3572 [POI2014]PTA-Little Bird 一只鸟从1跳到n.从1开始,跳到比当前矮的不消耗体力,否则消耗一点体力,每次询问有一个步伐限制k,求每次最少耗费多少体力 很简短的题目哼. 首先对于一个点, 他的状态一定是由前 \(k\) 个转移过来的. \(k\) 的长度在每组询问内一定, 想到用单调队列维护 \(dp\) . 不过此时单调队列里的元素有两个关键字: 劳累度和高度, 因为跳到比这个点高的树需要花费恒为一点体力(这个很重要), 所以我们维护单调队列的时候可以以劳累度为

单调队列应用--BZOJ 3831 Little Bird

3831: [Poi2014]Little Bird Time Limit: 20 Sec  Memory Limit: 128 MB Description In the Byteotian Line Forest there are   trees in a row. On top of the first one, there is a little bird who would like to fly over to the top of the last tree. Being in

luogu 2827 蚯蚓 单调队列/优先队列

易知可利用优先队列选取最大值: 但是通过分析可知,先取出的蚯蚓分开后仍然要比后分的长,所以可直接利用单调队列找队头即可,分三个单调队列,分别找未切割,切割,切割2三种情况 #include<bits/stdc++.h> #define rep(i,x,y) for(register int i=x;i<=y;i++) #define ll long long using namespace std; const int inf=2147483647; const int N=1e5+5;

LUOGU P2569 [SCOI2010]股票交易(单调队列优化dp)

传送门 解题思路 不难想一个\(O(n^3)\)的\(dp\),设\(f_{i,j}\)表示第\(i\)天,手上有\(j\)股的最大收益,因为这个\(dp\)具有单调性,所以\(f_i\)可以贪心的直接从\(f_{i-w-1}\)那一层转移来,转移时枚举一下当前买卖多少.考虑优化,发现每次其实就是一个区间取\(max\),是由\(AS\)和\(BS\)所限制的区间,所以单调队列优化就好了,一个正着做一个倒着做,时间复杂度\(O(n^2)\) 代码 #include<bits/stdc++.h>

单调队列

先放上luogu的题目链接--滑稽窗口 然后我们再来讲单调队列 单调队列是指这样一种队列:在队列中的元素为单调递增状态或单调递减状态. 例如1 2 3 4 5和9 2 1都是单调队列,但1 2 2 3 4和4 3 4 5就不是单调队列. 但普通队列明显是维持不了单调队列的性质的. 为了维持单调队列的单调性质,我们只好想一些方法.方法就是修改队列的性质.单调队列不仅队头可以出队,队尾也可以出队. 比如说有一个单调队列是 1 3 7 8 现在突然要从队尾进来一个6如果单纯的把6插进队尾的话,那这个队