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 }