T1:
小喵喵有
现在小喵喵要吃掉一些小鱼干,出于一些原因,小喵喵会吃掉连续的一段区间中的所有小鱼干。
如果吃掉了 一段区间,那么小喵喵会获得一些满意度。
形式化地,总满意度
由于只有小喵喵最喜欢的小鱼干的特殊度等于
现在小喵喵可以选择任意一段区间(不能为空),但是有一些小鱼干的美味度是负数,吃掉所有小鱼干不一定会获得最多的满意度。所以小喵喵想知道最大能获得的总满意度是多少。
思路:
模拟+优化
首先可以想到n*n的模拟,但是复杂度过高于是我们想到:
可以在每个bi等于1的点预处理一个数组,表示这个点向左最大能延伸到多少
这样我们在枚举每个点的时候就只需要枚举在它之前有多少个bi为1的点就可以了
但是只是这样还是有问题的,如果最大值是不经过任何一个bi为1的点结果就是有问题的
所以我们需要再单独跑一遍判断
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cmath> 5 #include<cstring> 6 #include<cstdlib> 7 #include<set> 8 #include<map> 9 #include<vector> 10 #include<stack> 11 #include<queue> 12 #define ll long long 13 #define inf 2147383611 14 #define MAXN 101010 15 #define MOD 16 using namespace std; 17 inline ll read() 18 { 19 ll x=0,f=1; 20 char ch;ch=getchar(); 21 while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();} 22 while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();} 23 return x*f; 24 } 25 ll n,a[MAXN],k[MAXN],cnt,sa[MAXN],b[MAXN],ans,m[MAXN],x; 26 int main() 27 { 28 n=read(); 29 for(int i=1;i<=n;i++) {a[i]=read();sa[i]=sa[i-1]+a[i];} 30 for(int i=1;i<=n;i++) {x=read();b[i]=b[i-1]+x;if(x) k[++cnt]=i;} 31 k[0]=0,k[cnt+1]=n+1; 32 //for(int i=1;i<=cnt+1;i++) cout<<i<<" "<<k[i]<<endl; 33 ll tmp,_max; 34 memset(m,-127,sizeof(m)); 35 for(int i=1;i<=cnt;i++) 36 { 37 tmp=0,_max=a[k[i]]; 38 for(int j=k[i];j>k[i-1];j--) 39 { 40 tmp+=a[j]; 41 if(tmp>=_max) {m[i]=j;_max=tmp;} 42 } 43 } 44 //for(int i=1;i<=cnt;i++) cout<<m[i]<<endl; 45 ll res; 46 if(b[1]) ans=sa[1]*b[1]; 47 else ans=sa[1]; 48 for(int i=1;i<=n;i++) 49 { 50 if(b[i]) ans=max(ans,sa[i]*b[i]); 51 else ans=max(sa[i],ans); 52 for(int j=b[i];j>=1;j--) 53 { 54 ans=max(ans,(sa[i]-sa[m[j]-1])*(b[i]-j+2)); 55 //cout<<i<<" "<<j<<" "<<(sa[i]-sa[k[j]-1])*(b[i]-j+2)<<endl; 56 } 57 } 58 for(int i=1;i<=cnt+1;i++) 59 { 60 tmp=-inf; 61 for(int j=k[i-1]+1;j<k[i];j++) 62 { 63 if(tmp<0&&a[j]<=0) tmp=max(tmp,a[j]); 64 if(tmp>=0) tmp+=a[j]; 65 if(tmp<0&&a[j]>0) tmp=a[j]; 66 ans=max(ans,tmp); 67 //cout<<i<<" "<<j<<" "<<tmp<<endl; 68 } 69 } 70 printf("%lld",ans); 71 }