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],显然就是一个维护移动的给定长度的区间最值问题。
因为如果一个f[j]不是目前的最小值,那么最小值+1也只会<=。我们的最优值没有改变。原谅我是语死早
所以我们只需要在f[j]最小的情况下满足a[j]最小即可。
此外,如果跳一次+2的话好像不能这么做? 也能这么做,/2即可。。。
代码:

 1 #include<cstdio>
 2
 3 #include<cstdlib>
 4
 5 #include<cmath>
 6
 7 #include<cstring>
 8
 9 #include<algorithm>
10
11 #include<iostream>
12
13 #include<vector>
14
15 #include<map>
16
17 #include<set>
18
19 #include<queue>
20
21 #include<string>
22
23 #define inf 1000000000
24
25 #define maxn 1000000+5
26
27 #define maxm 200000+5
28
29 #define eps 1e-10
30
31 #define ll long long
32
33 #define pa pair<int,int>
34
35 #define for0(i,n) for(int i=0;i<=(n);i++)
36
37 #define for1(i,n) for(int i=1;i<=(n);i++)
38
39 #define for2(i,x,y) for(int i=(x);i<=(y);i++)
40
41 #define for3(i,x,y) for(int i=(x);i>=(y);i--)
42
43 #define for4(i,x) for(int i=head[x],y=e[i].go;i;i=e[i].next,y=e[i].go)
44
45 #define for5(n,m) for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)
46
47 #define mod 1000000007
48
49 using namespace std;
50
51 inline int read()
52
53 {
54
55     int x=0,f=1;char ch=getchar();
56
57     while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();}
58
59     while(ch>=‘0‘&&ch<=‘9‘){x=10*x+ch-‘0‘;ch=getchar();}
60
61     return x*f;
62
63 }
64 int n,m,k,a[maxn],f[maxn],q[maxn];
65
66 int main()
67
68 {
69
70     freopen("input.txt","r",stdin);
71
72     freopen("output.txt","w",stdout);
73
74     n=read();
75     for1(i,n)a[i]=read();
76     m=read();
77     while(m--)
78     {
79         k=read();
80         int l=1,r=1;q[1]=1;f[1]=0;
81         for2(i,2,n)
82         {
83             while(l<r&&i-q[l]>k)l++;
84             f[i]=f[q[l]]+(int)(a[q[l]]<=a[i]);
85             while(l<=r&&(f[i]<f[q[r]]||(f[i]==f[q[r]]&&a[i]>a[q[r]])))r--;
86             q[++r]=i;
87         }
88         printf("%d\n",f[n]);
89     }
90
91     return 0;
92
93 }  

时间: 2025-01-01 08:30:25

BZOJ3831: [Poi2014]Little Bird的相关文章

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;

【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: [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

P3572 [POI2014]PTA-Little Bird

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

[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

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

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

DAY 3 上午

状压DP 状态压缩dp 状态压缩是设计dp状态的一种方式. 当普通的dp状态维数很多(或者说维数与输入数据有关),但每一维总量很少时,可以将多维状态压缩为一维来记录. 这种题目最明显的特征就是:都存在某一给定信息的范围非常小(在20以内),而我们在dp中所谓压缩的就是这一信息. (或者是在做题过程中分析出了某一信息种类数很少) 我们来看个例子. 经典题 ?给出一个n*m的棋盘,要放上一些棋子,要求不能有任意两个棋子相邻.求方案数. ? n<=100; ?m<=8. 如果m固定的话可以设f[i]