小C的数学问题
时间限制: 1 Sec 内存限制: 128 MB
提交: 203 解决: 44
[提交] [状态] [命题人:外部导入]
题目描述
小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
查询区间值用线段树(这里说一下,如果不用线段树直接上来二分,每一次遍历去查找最小值会tle)
之后整体采用二分思想,比较当前区间、左区间和右区间。
#include<stdio.h>
#include<bits/stdc++.h>
using namespace std;
#define Max 100005
#define ll long long
ll sum[Max];
struct data
{
ll l,r,minnum;
ll minloc;
} node[4*Max];
ll score[Max];
ll ansl=0,ansr=0,last=-1;
ll min(ll a,ll b)
{
return a<b?a:b;
}
void Buildnode(ll left,ll right,ll num)
{
node[num].l=left;
node[num].r=right;
if(left==right)
{
node[num].minnum=score[left];
node[num].minloc=left;
return;
}
else
{
Buildnode(left,(left+right)>>1,2*num);
Buildnode(((left+right)>>1)+1,right,2*num+1);
if(node[2*num].minnum<node[2*num+1].minnum)
node[num].minnum=node[2*num].minnum,node[num].minloc=node[2*num].minloc;
else
node[num].minnum=node[2*num+1].minnum,node[num].minloc=node[2*num+1].minloc;
}
}
ll loc,N;
ll Query(ll left,ll right,ll num)
{
if(node[num].l==left && node[num].r==right){
return node[num].minnum;
}
if(right<=node[2*num].r)
return Query(left,right,2*num);
if(left>=node[2*num+1].l)
return Query(left,right,2*num+1);
ll mid=(node[num].l+node[num].r)>>1;
return min(Query(left,mid,2*num),Query(mid+1,right,2*num+1));
}
ll deal(ll left,ll right){
if(left>right)
return 0;
if(left==right)
{
ll now=score[left]*score[left];
if(now>last)
{
last=now;
ansl=left,ansr=right;
}
return now;
}
ll minnum=Query(left,right,1);
ll now=(sum[right]-sum[left-1])*minnum;
if(now>last){
last=now;
ansl=left,ansr=right;
}
int pos;
for(ll i=left;i<=right;i++)
{
if(score[i]==minnum){
pos=i;
break;
}
}
return max(now,max(deal(left,pos-1),deal(pos+1,right)));
}
int main()
{
ll M;
while(scanf("%lld",&N)!=EOF)
{
ll i;
memset(sum,0,sizeof(sum));
for(i=1; i<=N; i++)
{
scanf("%lld",&score[i]);
sum[i]=sum[i-1]+score[i];
}
Buildnode(1,N,1);
deal(1,N);
printf("%lld\n",last);
printf("%lld %lld\n",ansl,ansr);
}
return 0;
}