洛谷 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 }

 

posted @ 2020-02-15 23:51  尹昱钦  阅读(222)  评论(0编辑  收藏  举报