The Preliminary Contest for ICPC China Nanchang National Invitational I.Max answer單調棧
阿新 • • 發佈:2019-04-22
anti 有變 定義 else ont def 所有 註意 復雜
題面
題意:一個5e5的數組,定義一個區間的值為 這個區間的和*這個區間的最小值,註意數組值有負數有正數,求所有區間中最大的值
題解:如果全是正數,那就是原題 POJ2796 單調棧做一下就ok
我們現在有負數,考慮這段區間,他的和必須是負數,由於導致和為負數,最小值一定也是負數,
那對於這樣一個和為負的區間進行擴展的時候,遇見下一個數,是負數,我們一定會擴展,無論這個負數大小
遇見下一個是正數,如果和沒有變正,那就可以繼續擴展下去(不更新答案罷了)
所以我們對於那些和為負的區間,單獨統計一下答案就好了,順路就統計這個區間的最小值,因為一旦拋棄她就再也不會回頭了!
所以壓根不用線段樹 ST表之類的,對於負數的和,整體按POJ2796做的取個min,就行了.復雜度O(n)
1 #include<bits/stdc++.h> 2 #define lld long long 3 #define N 500050 4 using namespace std; 5 int n; 6 lld a[N],sum[N],x[N],xx[N]; 7 lld L[N],R[N],ansv,ans1; 8 int main () 9 { 10 scanf("%d", &n); 11for (int i=1;i<=n;i++) 12 { 13 scanf("%lld",&x[i]); 14 xx[i]=x[i]; 15 } 16 lld ww=xx[1],minx=xx[1]; 17 for (int i=1;i<=n;i++) 18 { 19 if (xx[i-1]<0) 20 { 21 minx=min(minx,xx[i]); 22 xx[i]+=xx[i-1]; 23 }else 24 { 25 xx[i]+=0; 26 minx=1e18; 27 } 28 if (xx[i]<ww) 29 { 30 ww=xx[i]; 31 ansv=minx; 32 } 33 } 34 if (ww<0) ans1=ww*ansv; 35 for (int i=1;i<=n;i++) a[i]=x[i]; 36 for (int i=1;i<=n;i++) 37 { 38 sum[i]=sum[i-1]+a[i]; 39 L[i]=R[i]=i; 40 } 41 a[0]=a[n+1]=-1e9; 42 for (int i=1;i<=n;i++) 43 while(a[i]<=a[L[i]-1]) L[i]=L[L[i]-1]; 44 for (int i=n;i>=1;i--) 45 while(a[i]<=a[R[i]+1]) R[i]=R[R[i]+1]; 46 lld ans=-1e18,l,r; 47 for (int i=1;i<=n;i++) 48 { 49 lld T=a[i]*(sum[R[i]]-sum[L[i]-1]); 50 if(ans<T) ans=T,l=L[i],r=R[i]; 51 } 52 cout<<max(ans,ans1)<<endl; 53 }
The Preliminary Contest for ICPC China Nanchang National Invitational I.Max answer單調棧