1. 程式人生 > >P2629 好消息,壞消息

P2629 好消息,壞消息

預處理 有一個 sca 一個 老板 部分 ostream 輸入輸出 math

題目描述

uim在公司裏面當秘書,現在有n條消息要告知老板。每條消息有一個好壞度,這會影響老板的心情。告知完一條消息後,老板的心情等於之前老板的心情加上這條消息的好壞度。最開始老板的心情是0,一旦老板心情到了0以下就會勃然大怒,炒了uim的魷魚。

uim為了不被炒,知道了了這些消息(已經按時間的發生順序進行了排列)的好壞度,希望研究如何不讓老板發怒。

uim必須按照時間的發生順序逐條將消息告知給老板。不過uim可以使用一種叫“倒敘”的手法,例如有n條消息,小a可以從k,k+1,k+2...n,1,2...k-1這種順序通報。

他希望知道,有多少個k,從k開始通報到n然後從1通報到k-1可以讓老板不發怒。

輸入輸出格式

輸入格式:

第一行一個整數n(1 <= n <= 10^6),表示有n個消息。

第二行n個整數,按時間順序給出第i條消息的好壞度Ai(-1000 <= Ai <= 1000)

輸出格式:

一行一個整數,表示可行的方案個數。

輸入輸出樣例

輸入樣例#1:
4
-3 5 1 2 
輸出樣例#1:
2

說明

樣例解釋

[5 1 2 -3]或[1 2 -3 5]

對於25%數據n<=1000

對於75%數據n<=10000

對於100%數據n<=10^6

數據範圍N*N去搜,肯定不行。

那就預處理一遍,前綴最小值,部分區間的的前綴最小值

#include<iostream>
#include
<cstdio> #include<string.h> #include<algorithm> #include<math.h> using namespace std; int n,ans; int tot=0; int f1[2000009],f2[3000009]; int sum[2000009],a[2000009]; int main() { scanf("%d",&n); f1[0]=99999999; for(int i=1;i<=n;i++) { scanf("%d",&a[i]);tot+=a[i]; f1[i]
=min(f1[i-1],tot); } sum[n]=a[n];f2[n]=a[n]; for(int i=n-1;i>=1;i--) { sum[i]=sum[i+1]+a[i]; f2[i]=min(a[i],f2[i+1]+a[i]); } f1[0]=0; for(int i=1;i<=n;i++) if(f2[i]>=0&&sum[i]+f1[i]>=0) ans++; cout<<ans; }

P2629 好消息,壞消息