洛谷 P2422 良好的感觉

本文介绍了一种人体舒适度分析算法,通过分析连续N天的人体感受值,找到最舒适时间段及其舒适值。采用倍增技术和st表预处理,优化算法至O(NlogN)。适用于大数据分析和人体工效学研究。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目描述

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 ;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值