版权声明:本文为博主原创文章,转载请注明出处( • ̀ω•́ )✧ https://blog.csdn.net/wangws_sb/article/details/89034445
问题 J: 小C的数学问题
时间限制: 1 Sec 内存限制: 128 MB
提交: 398 解决: 84
[提交] [状态] [命题人:外部导入]
题目描述
小C是个云南中医学院的大一新生,在某个星期二,他的高数老师扔给了他一个问题。
让他在1天的时间内给出答案。
但是小C不会这问题,现在他来请教你。
请你帮他解决这个问题。
有n个数,每个数有权值。
数学老师定义了区间价值为区间和乘上区间内的最小值。
现在要你找出有最大区间价值的区间是什么,并输出区间价值。
输入
每个输入文件只包含单组数据。
第一行一个整数n。(1 <= n <= 100000)
第二行n个整数a_1,a_2,...,a_n。(0 <= a_i <= 1000000)
输出
第一行输出一个整数,表示最大的区间价值。
第二行输出两个整数,表示区间的起点和终点。
保证答案唯一。
样例输入
复制样例数据
6 10 1 9 4 5 9
样例输出
108 3 6
解题思路:将arr[i]作为最小值,分别寻找左边比arr[i]小的那个位置的后一个位置和右边比arr[i]小的那个位置的前一个位置,但是直接暴力会超时,可以优化查找左边比arr[i]小的位置和右边比arr[i]小的位置,用set维护
AC代码:
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <map>
#include <set>
using namespace std;
#define io ios::sync_with_stdio(0),cin.tie(0)
#define ms(arr) memset(arr,0,sizeof(arr))
#define mc(a,b) memcpy(a,b,sizeof(b))
#define inf 0x3f3f3f
#define fin freopen("in.txt", "r", stdin)
#define fout freopen("out.txt", "w", stdout)
typedef long long ll;
typedef unsigned long long ULL;
const int mod=1e9+7;
const int N=1e5+7;
struct node
{
int x;
int id;
}arr[N];
int n;
ll sum[N];
set <ll> s1,s2;
bool cmp(node a,node b)
{
return a.x<b.x;
}
int main()
{
cin>>n;
sum[0]=0;
for(int i=1;i<=n;i++){
cin>>arr[i].x;
arr[i].id=i;
sum[i]=sum[i-1]+arr[i].x;
}
sort(arr+1,arr+n+1,cmp);
set<ll>::iterator it;
s1.clear();
s2.clear();
s1.insert(n+1);
s2.insert(n+1);
int i=1;
int l,r,t1,t2;
ll ma=-1;
int L,R;
while(i<n+1)
{
l=r=i;
while(arr[l].x==arr[r+1].x&&r<=n) r++;
for(int j=l;j<=r;j++)
{
it=s1.lower_bound(n+1-arr[j].id);
t1=n+1-*it;
it=s2.lower_bound(arr[j].id);
t2=*it;
ll ans=(sum[t2-1]-sum[t1])*arr[i].x;
if(ans>ma)
{
ma=ans;
L=t1+1;
R=t2-1;
}
}
for(int j=l;j<=r;j++)
{
s1.insert(n+1-arr[j].id);
s2.insert(arr[j].id);
}
i=r+1;
}
cout<<ma<<endl;
cout<<L<<" "<<R<<endl;
return 0;
}