洛谷 P2629 好消息,坏消息(前缀和,单调队列,断环为链)
传送门
解题思路
主要思想是断环为链。
把数组开双倍大小,然后在n后面接上1~n-1,这样的好处是所有的长度为n的链都包含在内。
然后对于每一个长度为n的区间i......j,我们要做的是判断是否存在一个点k,使得i.....k的和小于0。
对的,和!
前缀和!
然后要找一个最小的前缀和!
长度为n的区间内的最小值?
emm,单调队列!
此题毕。
(明天开始上网课了qwq)
(期待老师的直播)
AC代码
1 #include<iostream> 2 #include<cstdio> 3 #include<queue> 4 using namespace std; 5 const int maxn=1000005; 6 int n,a[maxn*2],d[maxn*2],ans; 7 deque<int> q; 8 int main() 9 { 10 cin>>n; 11 for(int i=1;i<=n;i++){ 12 scanf("%d",&a[i]); 13 } 14 for(int i=1;i<n;i++){ 15 a[i+n]=a[i]; 16 } 17 for(int i=1;i<=n+n-1;i++){ 18 d[i]=d[i-1]+a[i]; 19 } 20 for(int i=1;i<=2*n-1;i++){ 21 if(q.empty()) q.push_front(i); 22 else{ 23 if(i-q.back()>=n) q.pop_back(); 24 while(!q.empty()&&d[q.front()]>=d[i]) q.pop_front(); 25 q.push_front(i); 26 } 27 if(i>=n){ 28 if(d[q.back()]-d[i-n]>=0) ans++; 29 } 30 } 31 cout<<ans; 32 return 0; 33 }