2019牛客多校训练第四场C.sequence(线段树+单调栈+前缀和)
题目传送门 题意 输入整数n,给出两个包含n个整数的序列a和b,找到一个区间[l,r],使在该区间内a序列最小值×b序列区间和的值最大。 题解 遍历a序列,维护单调栈求以当前值a[i]为最小值时的最大可达区间[ L[i],R[i] ](即最大左右边界); b序列先预处理其前缀和pre_sum,后用线段树维护pre_sum数组的区间最值;所以答案就是a[i]×b序列在[ L[i],R[i] ]区间内的和的最大值,不断更新最优解求最大结果即可。 当a[i]≥0时,b序列在[ L[i],R[i] ]区间内的和的最大值为b序列前缀和数组后半部分最大值-前半部分最小值,即: max( [pre_sum(i),pre_sum(R[i])] )-min( [pre_sum(L[i]-1),pre_sum(i-1)] ); 当a[i]<0时,b序列在[ L[i],R[i] ]区间内的和的最大值为b序列前缀和数组后半部分最小值-前半部分最大值,即: min( [pre_sum(i),pre_sum(R[i])] )-max( [pre_sum(L[i]-1),pre_sum(i-1)] ); 时间复杂度O(nlogn)。 Code 1 /*2442ms*/ 2 #include<bits/stdc++.h> 3 using namespace std; 4 typedef long long ll;