P3572 [POI2014]PTA-Little Bird

P3572 [POI2014]PTA-Little Bird

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



很简短的题目哼。

首先对于一个点, 他的状态一定是由前 \(k\) 个转移过来的。 \(k\) 的长度在每组询问内一定, 想到用单调队列维护 \(dp\) 。

不过此时单调队列里的元素有两个关键字: 劳累度和高度, 因为跳到比这个点高的树需要花费恒为一点体力(这个很重要), 所以我们维护单调队列的时候可以以劳累度为第一关键字, 高度为第二关键字进行比较, 为多个关键字的单调队列

解释一下为什么体力花费恒为一点很重要。 这里运用了一点贪心的思想: 此题的高度对体力消耗没有影响, 只有高和矮两种说法。 只要我的劳累值比你小, 不管你的高度有多低, 我 $ + 1$ 一定 \(<=\) 你, 所以可以把高度作为第二关键字比较, 从而不影响结果

Code

教训: 多次调用简单函数会大大降低算法的效率, 开一波 \(O2\) 才没 \(T\) 。

// luogu-judger-enable-o2
#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
#include<algorithm>
#define LL long long
using namespace std;
int RD(){
    int flag = 1, out = 0;char c = getchar();
    while(c < '0' || c > '9'){if(c == '-')flag = -1;c = getchar();}
    while(c >= '0' && c <= '9'){out = out * 10 + c - '0';c = getchar();}
    return flag * out;
    }
const int maxn = 1000019;
int len, num ,k;
int h[maxn];
int dp[maxn];
struct Que{
    int h, val, index;
    Que (int h, int val, int index): h(h), val(val), index(index){}
    Que(){};
    bool operator < (Que const &a)const{
        if(val != a.val)return val < a.val;
        return h > a.h;
        }
    }Q[maxn];
int head, tail;
void push_back(Que x){
    while(head <= tail && x < Q[tail])tail--;
    Q[++tail] = x;
    }
void check(int x){
    while(x - Q[head].index > k)head++;
    }
int get_min(){return Q[head].val;}
int main(){
    len = RD();
    for(int i = 1;i <= len;i++)h[i] = RD();
    num = RD();
    while(num--){
        k = RD();
        head = 1, tail = 0;Q[head] = Que(1e9 + 19, 0, 0);
        memset(dp, 0, sizeof(dp));
        for(int i = 1;i <= len;i++){
            check(i);
            if(h[i] < Q[head].h)dp[i] = get_min();
            else dp[i] = get_min() + 1;
            push_back(Que(h[i], dp[i], i));
            }
        printf("%d\n", dp[len]);
        }
    return 0;
    }

原文地址:https://www.cnblogs.com/Tony-Double-Sky/p/9339048.html

时间: 2024-11-13 06:52:32

P3572 [POI2014]PTA-Little Bird的相关文章

[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 s

日照——栈与队列

P1054 等价表达式 题目描述 明明进了中学之后,学到了代数表达式.有一天,他碰到一个很麻烦的选择题.这个题目的题干中首先给出了一个代数表达式,然后列出了若干选项,每个选项也是一个代数表达式,题目的要求是判断选项中哪些代数表达式是和题干中的表达式等价的. 这个题目手算很麻烦,因为明明对计算机编程很感兴趣,所以他想是不是可以用计算机来解决这个问题.假设你是明明,能完成这个任务吗? 这个选择题中的每个表达式都满足下面的性质: 1. 表达式只可能包含一个变量‘a’. 2. 表达式中出现的数都是正整数

bzoj 3831: [Poi2014]Little Bird

3831: [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 the

【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

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

BZOJ 3831: [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 the strength to fly there with

【单调队列】【动态规划】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;

BZOJ 3831 POI2014 Litter Bird

dp[i]表示前i棵树的最小体力消耗值但是如果直接上肯定时间复杂度会爆炸 (N*Q*K)N和Q已经无法优化所以需要优化k 通过一种数据结构找到 k个位置中最合适的位置 从而达到N*Q的时间复杂度 线段树和树状数组略有吃力,所以需要根据题目的单调性需要单调队列. 什么情况需要优化呢?1.当前的位置dp值相等 但比之前的k个数的中某个数大 那肯定保留大的2.如果dp值不相等 肯定保留小的那个位置 代码实现前仔细思考!!!! 1 #include <cstdio> 2 #include <qu

BZOJ3831: [Poi2014]Little Bird

题目:http://www.lydsy.com/JudgeOnline/problem.php?id=3831 题意: 有一排n棵树,第i棵树的高度是Di. MHY要从第一棵树到第n棵树去找他的妹子玩. 如果MHY在第i棵树,那么他可以跳到第i+1,i+2,...,i+k棵树. 如果MHY跳到一棵不矮于当前树的树,那么他的劳累值会+1,否则不会. 为了有体力和妹子玩,MHY要最小化劳累值.题解:f[i]=min(f[j]+a[j]<=a[i])  i-j<=k如果没有a[j]<=a[i]