Blue:贪心,单调队列

Posted hzoi-deepinc

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Blue:贪心,单调队列相关的知识,希望对你有一定的参考价值。

考场上什么都没想。

显然在扯淡了,应该说是刚开始想了一些没用的。

有决策单调性,所以二分答案?

好,那就二分答案。想想怎么检查每只蛤能不能都跳到终点?

那么每只蛤都不能掉队啊。

如果你现在遇到了一个石头,你就会优先让最落后的那只蛤跳过来蛤。(因为都不能掉队啊)

如果它离的太远跳不过来了,那么这只蛤就永远地掉队了。

嗯,这个想法还是比较简单的吧。

然后我们可以发现这个思路貌似是普适的。我们现在去掉二分答案。

所以现在问题不再是检查是否都不掉队,而是直接询问有多少个蛤能过去。

继续上面的思路,让最落后的蛤尝试跳过来,跳不过来就放弃它去让第二落后的蛤来。

然后有了这个思路就可以愉快的AC了。

当然我们需要证明(我没看题解,我自己口胡蛤)

对于任意多的蛤,分别标号为1234...,按照它们目前所在的位置排序

那么现在突然出现了一个石头用0表示:1234...0

现在要用蛤来跳,按照刚才的策略你会让1跳得到234...1

其它决策无非就2种,

一种是这块石头所有蛤都无视它:这一定不优,如果你要忽视它还要跳到后面,那么你在这里歇一下脚再往后跳当然不会变差啦

另一种就是让不是最落后的蛤跳到上面:你会得到12x4...3之类的(x表示被踩沉了的石头)

相较于最优决策,区别就是有一只还在原来的最落后位置,而最优决策下有一只蛤更靠前了一点(至少不再是那个最落后位置了)

而还在最落后位置上的那只蛤可能从此就掉队了,故这个决策不优。

所以维护一个队列,表示目前还没有被放弃的蛤的位置。

枚举每块石头,让队首的蛤不能跳就放弃,能跳就跳,把它从队首改变位置放到队尾。

因为石头已经排序,所以加入队尾的元素一定是递增的,所以队列自带单调。

所有的石头都跳完之后,队列里的蛤不能跳到终点的就放弃。

最后队列里有几个蛤就是几啦。

多测清空!蛤的初始位置重置为0!

技术图片
 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int n,m,d,l,x[1000005],q[2000005],t,h,T;
 4 int main()//freopen("blue.in","r",stdin);
 5     scanf("%d",&T);
 6     while(T--)
 7         scanf("%d%d%d%d",&n,&m,&d,&l);
 8         for(int i=1;i<=n;++i)scanf("%d",&x[i]);
 9         h=1;t=m;for(int i=1;i<=m;++i)q[i]=0;
10         for(int i=1;i<=n;++i)
11             while(q[h]+d<x[i]&&h<=t)++h;
12             ++h;q[++t]=x[i];
13         
14         while(q[h]+d<l&&h<=t)h++;
15         if(t-h==m-1)puts("Excited");
16         else printf("%d\n",t-h+1);
17     
18 
代码复杂度:462B

 

以上是关于Blue:贪心,单调队列的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ 2424 订货(贪心+单调队列)

买卖股票的最佳时期(贪心+单调队列)

买卖股票的最佳时期(贪心+单调队列)

贪心/DP/单调队列CF1029BCreating the Contest

单调队列优化DP烽火传递 LibreOJ - 10180

USACO 2009 Open 干草塔 Tower of Hay(贪心+单调队列优化DP)