P2629 好消息,坏消息

原题链接

单调队列+前缀和

之前一直不理解滑动窗口,通过这道题理解了点,i是窗口右边节点,i-k+1是窗口左边界点,而单调队列是用来求该窗口相关属性的一个工具,q[hh]不一定等于窗口的左边界.

比如,本道题q[hh]是用来求窗口下最小和的下标,与i-k+1的下标无关,我们求cnt是否+1只需要判断左边界是否>0&&最小和-左边界-1的前缀和是否>0即可

这里还有个技巧,破环为链:详情看这篇题解 链接 ,这里的2不能重复,因为下标最多到4

下面贴代码:

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 const int N = 1e6+10;
 4 int a[N*2],sum[N*2],q[N*2];
 5 int main()
 6 {
 7     int n,cnt = 0,tt = -1,hh = 0;
 8     scanf("%d",&n);
 9     for(int i=1;i<=n;i++) scanf("%d",&a[i]);
10     for(int i=n+1;i<2*n;i++) a[i] = a[i%n];
11     for(int i=1;i<2*n;i++) sum[i] = sum[i-1]+a[i];
12     for(int i=1;i<n*2;i++){
13         while(hh<=tt&&i-q[hh]+1>n) ++hh;
14         while(hh<=tt&&sum[q[tt]]>=sum[i]) --tt;
15         q[++tt] = i;
16         if(i-n+1>0&&sum[q[hh]]-sum[i-n]>=0) cnt++;
17     }
18     printf("%d\n",cnt);
19     return 0;
20 }

 

posted @ 2020-12-27 19:12  acmloser  阅读(84)  评论(0编辑  收藏  举报