BZOJ 3831 [Poi 2014] Little Bird

来源:互联网 发布:131458查询淘宝账号 编辑:程序博客网 时间:2024/04/30 20:58

3831: [Poi2014]Little Bird

Time Limit: 20 Sec  Memory Limit: 128 MB
Submit: 121  Solved: 68
[Submit][Status]

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 without any stop. If the bird is sitting on top of the tree no.  , then in a single flight leg it can fly to any of the trees no.i+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 least as 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 least tiresome, 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 get from 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  . Help all the birds, little and big!
有一排n棵树,第i棵树的高度是Di。
MHY要从第一棵树到第n棵树去找他的妹子玩。
如果MHY在第i棵树,那么他可以跳到第i+1,i+2,...,i+k棵树。
如果MHY跳到一棵不矮于当前树的树,那么他的劳累值会+1,否则不会。
为了有体力和妹子玩,MHY要最小化劳累值。

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

HINT

Explanation: The first bird may stop at the trees no. 1, 3, 5, 7, 8, 9. Its tiresome flight legs will be the one from the 3-rd tree to the 5-th one and from the 7-th to the 8-th.


Solution

这个题感觉比较厉害。
对于每个询问,我们肯定是要 O(n) 回答的。
大家可能会想到线段树之类的,
但 Q * n = 25000000 。
再来个 log 就会 T 得死死的。
除非大家卡卡常数之类的。。。
好吧。这个题的做法是单调队列优化动态规划。
很显然我们可以设 Dp[i] 为跳到这颗树的最小劳累值。
然后由于决策区间是单调的。
于是我们以 Dp[] 为第一关键字,树高为第二关键字维护单调队列。
队列元素关系满足:
对于任意在队列的元素 i < j ,有 Dp[i]  < Dp[j] || (Dp[i] == Dp[j] && Height[i] > Height[j])
每次决策就从队首转移。
于是可以做到 O(n) 回答询问。
于是整个题就是 O(Qn) 的了。
同时也要注意一些小细节,详情见代码。
然后由于我太弱,一开始居然没有输出东西,然后快速读入也写错了,
于是就 WA 了两遍。TAT
毕竟 Gromah 太弱,只会做水题。

Gromah's Code

#include <cmath>#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>using namespace std;#define N 1000000 + 5int n, A[N], q[N], Dp[N];inline int getint(){char ch = '\n';for (; ch > '9' || ch < '0'; ch = getchar()) ;int res = ch - '0';for (ch = getchar(); ch >= '0' && ch <= '9'; ch = getchar())res = (res << 3) + (res << 1) + ch - '0';return res;}inline void Solve(int k){int head = 1, tail = 0;for (int i = 1; i <= n; i ++){while (head <= tail && q[head] + k < i)head ++;Dp[i] = i == 1 ? 0 : Dp[q[head]] + (A[q[head]] <= A[i]);while (head <= tail && (Dp[i] < Dp[q[tail]] || Dp[i] == Dp[q[tail]] && A[i] >= A[q[tail]]))tail --;q[++ tail] = i;}printf("%d\n", Dp[n]);}int main(){n = getint();for (int i = 1; i <= n; i ++)A[i] = getint();int T = getint();while (T --)Solve(getint());return 0;}


0 0