1. 程式人生 > >Day6-T3

Day6-T3

原題目

  某個帝國修了一條非常非常長的城牆來抵禦外敵,城牆共分N段,每一段用一個整數來描述堅固程度。

  過了幾年,城牆年久失修,有很多段都己經損壞,於是皇帝決定派你去修理城牆,但是經費有限.

  所以你準備先考察一下城牆如果一段連續的城牆它們的堅固程度之和>0,邵麼我們認為這段城牆暫時有效。

  例如

  5

  -5 1 - 3 2 3

  這段城牆共分5段,堅固程度之和=1.要比0大,我們認為它還算有效

  下面告訴你N段城牆的堅固情況。

  請你求出最長的一段連續的城牆,要求堅固程度之和>0

  第1行是一個數N。

  第2行共N個整數,Ai描述第i段城牆的堅固程度:

  輸出共一行一個整數,最長的一段連續城牆的長度;

S1:

  Input:

10
-1 0 -1 2 0 -1 -1 2 -1 0

  Output:

7

 


 

  Describe:維護一個字首和單調減的佇列,保證後面減前面[也就是sum[l->r]]為正。

  code:

#include<bits/stdc++.h>
#define rep(a,b) for(register int i=(a);i<=(b);i++)
#define per(a,b) for(register int i=(a);i>=(b);i--)
using
namespace std; long long l,r,n,ans,tot,a[5959595],q[5050505],now; inline int read(){ int ret=0,f=1;char ch=getchar(); while (ch<'0'||ch>'9') {if (ch=='-') f=-f;ch=getchar();} while (ch>='0'&&ch<='9') ret=ret*10+ch-'0',ch=getchar(); return ret*f; } int main(){ n
=read(); for(int i=1;i<=n;i++)a[i]=a[i-1]+read(); for(int i=1;i<=n;i++) { l=0,r=tot,now=0x7fffffff; //初始化 while(l<=r){ //二分,由於q是單調佇列,滿足單調性 long long mid=l+r>>1; if(a[i]>a[q[mid]])now=mid,r=mid-1; //找當前值[字首和]在q中的位置 else l=mid+1; } if(a[i]<a[q[tot]])q[++tot]=i; //無彈出,所以編號也滿足單調減。越前面的越好,對答案的貢獻越大[若在隊尾加入佇列] if(now!=0x7fffffff)ans=max(i-q[now],ans); //加入ans } cout<<ans; return 0; }