今天总算基本掌握了单调队列的知识点了,其实是挺简单的,做了两道单调队列的题,一道二分,下午网站不知什么原因又关闭了很长时间。
关于单调队列,无非就是按照字面意思,形成一个具有单调性的队列,不断的向队列里压进新数,如果新数进入后违反了数列原来的单调性,则把队列中栈顶元素抛出,继续比较,直到可以把新数压入。
第一道题是滑动窗口,给一串数,按照从数列首开始,以m为长度,向后移动,求移动完得出的窗口内的一系列最大值与最小值,这算是一道典型的单调队列题,因为求得是窗口不断移动时的最大,最小值,那么求两次单调队列即可,分别求递增与递减的,一次取出队首的元素,当然还要标记好该位置上的元素什么时候出列。关于这部分的核心代码:
flag=-1;
head=0;
memset(indx,0,sizeof(indx));
for(int i=0;i<n;i++)
{
while(flag>=head&&a[i]>=a[indx[flag]]) --flag;
indx[++flag]=i;
if(i-indx[head]==m) ++head;
mx[i]=a[indx[head]];
}
这里head与flag分别是两个指针,表示单调队列首尾的位置,indx[n],是用来标记该位置元素什么时候出列。
第二道题牛站队题就更加简单了,还是用两个指针,建立单调递减的数列,因为一旦前面的牛更高就挡前面牛视线,所以单调队列的性质,累加flag得到视线内牛的数量加和就是答案了。
另外,还做了一道二分题,这道题题意是若干件衣服,湿的程度不同,自然风干一分一个点,还有一个热机,可以一分钟干几个点,问给出的衣服要最少多长时间全干,拿到这道题我真反应不出这个可以用二分做,结果不出意料的超时了。这道题是通过二分枚举时间来找到最短时间,其中存在的单调关系就是简简单单的,时间越多越有可能干完,就这样寻找零点。另外这里还有关于求mid时间下能不能干完这些衣服的推导。
首先判断该时间能不能自然风干,如果不可以,设该衣服风干x1分钟,热机x2分钟那么x1+x2=mid,x1+m*x2>=a[i],x2>=(a[i]-mid)/(m-1),对(a[i]-mid)/(m-1)想上取整就是热机必须在该件衣服的时间,如果时间累加大于了mid那么就时间不够用。由此作为二分法的判断条件。