题目描述
kkk做了一个人体感觉分析器。每一天,人都有一个感受值Ai,Ai越大,表示人感觉越舒适。在一段时间[i, j]内,人的舒适程度定义为[i, j]中最不舒服的那一天的感受值 * [i, j]中每一天感受值的和。现在给出kkk在连续N天中的感受值,请问,在哪一段时间,kkk感觉最舒适?
输入输出格式
输入格式:
第一行为N,代表数据记录的天数
第二行N个整数,代表每一天的感受值
输出格式:
一行,表示在最舒适的一段时间中的感受值。
输入输出样例
输入样例#1:
6 3 1 6 4 5 2
输出样例#1:
60
说明
样例解释:
kkk最开心的一段时间是第3天到第5天,开心值:(6+4+5)*4=60
对于30%的数据,1<=N<=100
对于70%的数据,1<=N<=2000
对于100%的数据,1<=N<=100000,1<=感受值<=1000000
我一眼看上去,好像没有什么思路,于是我决定换一种思路来做
因为如果确定了一个点为最小值,那么可以达到的最舒服的天数就显而易见了
这样时间就优化到O(N^2),想起以前学LCA的时候用了倍增,于是我决定也用倍增
并且先用st表预处理一下时间直接优化到O(NlogN)
参考代码
#include <iostream>
#include <cstring>
using namespace std ;
typedef long long LL ;
const int N = 1e5 + 10 ;
int n , a[N] ;
int st[N][21] , log[N] ;
LL sum[N] ;
int solve ( int x , int y ) {
int z = log[y-x+1] ;
return min ( st[x][z] , st[y-(1<<z)+1][z] ) ;
}
void get ( int pos , int &l , int &r ) {
l = r = pos ;
for ( int j = 20 ; j >= 0 ; j -- ) {
if ( l - (1<<j) >= 1 && solve( l - (1<<j) , pos ) == a[pos] )
l = l - (1<<j) ;
if ( r + (1<<j) <= n && solve( pos , r + (1<<j) ) == a[pos] )
r = r + (1<<j) ;
}
}
LL maxx = 0 ;
int main() {
cin >> n ; log[0] = -1 ; int l , r ;
for ( int i = 1 ; i <= n ; i ++ )
cin >> a[i] , st[i][0] = a[i] , log[i] = log[i>>1] + 1 ;
for ( int i = 1 ; (1<<i) <= n ; i ++ )
for ( int j = 1 ; j + (1<<i) <= n ; j ++ )
st[j][i] = min ( st[j][i-1] , st[j+(1<<(i-1))][i-1] ) ;
for ( int i = 1 ; i <= n ; i ++ ) sum[i] = sum[i-1] + a[i] ;
for ( int i = 1 ; i <= n ; i ++ ) {
get ( i , l , r ) ;
if ( ( sum[r] - sum[l-1] ) * LL(a[i]) > maxx )
maxx = ( sum[r] - sum[l-1] ) * LL(a[i]) ;
}
cout << maxx << endl ; return 0 ;
}