1. 程式人生 > >南昌網絡賽 I. Max answer 單調棧

南昌網絡賽 I. Max answer 單調棧

strong first ali title rst 技術 區間最小值 all --

Max answer

題目鏈接

https://nanti.jisuanke.com/t/38228

Describe

Alice has a magic array. She suggests that the value of a interval is equal to the sum of the values in the interval, multiplied by the smallest value in the interval.

Now she is planning to find the max value of the intervals in her array. Can you help her?

Input

First line contains an integer n(1≤n≤5×105n(1 \le n \le 5 \times 10 ^5n(1n5×105).

Second line contains nnn integers represent the array a(−105≤ai≤105)a (-10^5 \le a_i \le 10^5)a(105ai?105).

Output

One line contains an integer represent the answer of the array.

樣例輸入

5

1 2 3 4 5

樣例輸出

36

題意
給你一個序列,對於每個連續子區間,有一個價值,等與這個區間和×區間最小值,
求所有子區間的最大價值是多少。

題解

a[i]表示第i位的權值,L[i]表示第i個數左邊第一個比他小的數,R[i]表示右邊第一個比它小的數。

我們可以用單調站求出來,不會可以先做洛谷的完美序列, https://www.luogu.org/problemnew/show/P2659

然後對於每一位i,如果a[i]為正數,我們可以求包含i的區間和最大的子區間,然後再乘上這個值,當然不能越過L[i]和R[i]。

我們怎麽求呢?

我們先定義sum(i,j)為i到j的區間和,再定義lmax[i]為以i 為右端點的使得區間和和最大的左端點位置,(即求一個l<=i,使得sum(l,i)最大)。

那麽,lmax[i]可以通過lmax[i-1]更新,這個就是一個貪心吧,分兩種情況:

1.sum(lmax[i-1],i-1)<0, 那麽lmax[i]=i.

2.sum(lmax[i-1],i-1)>0,lmax[i+1]=lmax[i].

相似的我們可以求出lmax[i],lmin[i],rmax[i]。對於i ,若a[i]>0,其最大貢獻就是sum(max(L[i]+1,lmax[i]),min(R[i]-1,rmax[i])*a[i]。負數類似。

這樣題目就做完啦,時間復雜度O(n)

代碼:

技術分享圖片
 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define N 3000050
 4 #define INF 0x7f7f7f7f
 5 #define ll long long
 6 template<typename T>void read(T&x)
 7 ll n,a[N],s[N],sk[N],L[N],R[N];
 8 ll Rmin[N],Lmin[N],Rmax[N],Lmax[N],ans,top;
 9 int main()
10 {
11 #ifndef ONLINE_JUDGE
12   freopen("aa.in","r",stdin);
13 #endif
14   ios::sync_with_stdio(false);
15   cin>>n;
16   for(ll i=1;i<=n;i++)cin>>a[i],s[i]=a[i]+s[i-1];
17   ans=a[1]*a[1];
18   sk[top=1]=0;
19   a[0]=-INF-1;
20   a[n+1]=-INF;
21   for(ll i=1;i<=n+1;i++)
22     {
23       while(a[i]<a[sk[top]])
24     R[sk[top--]]=i;
25       L[i]=sk[top];
26       sk[++top]=i;
27     }
28   Lmin[1]=1;
29   Lmax[1]=1;
30   Rmin[n]=n;
31   Rmax[n]=n;
32   for(ll i=2;i<=n;i++)
33     {
34       if (s[i-1]-s[Lmin[i-1]-1]>0)Lmin[i]=i;
35       else Lmin[i]=Lmin[i-1];
36       if (s[i-1]-s[Lmax[i-1]-1]<0)Lmax[i]=i;
37       else Lmax[i]=Lmax[i-1];
38     }
39   for(ll i=n-1;i>=1;i--)
40     {
41       if (s[Rmin[i+1]]-s[i]>0)Rmin[i]=i;
42       else Rmin[i]=Rmin[i+1];
43       if (s[Rmax[i+1]]-s[i]<0)Rmax[i]=i;
44       else Rmax[i]=Rmax[i+1];
45     }
46   ll l,r;
47   for(ll i=1;i<=n;i++)
48     {
49       if (a[i]<0)
50     {
51       l=max(L[i]+1,Lmin[i]);
52       r=min(R[i]-1,Rmin[i]);
53     }
54       else
55     {
56       l=max(L[i]+1,Lmax[i]);
57       r=min(R[i]-1,Rmax[i]);
58     }
59       ans=max((s[r]-s[l-1])*a[i],ans);
60     }
61   cout<<ans;
62 }
View Code

南昌網絡賽 I. Max answer 單調棧