POj-Feel Good-单调栈

来源:互联网 发布:06年韦德总决赛数据 编辑:程序博客网 时间:2024/06/14 08:22

问题描述:
Bill is developing a new mathematical theory for human emotions. His recent investigations are dedicated to studying how good or bad days influent people’s memories about some period of life.
A new idea Bill has recently developed assigns a non-negative integer value to each day of human life.
Bill calls this value the emotional value of the day. The greater the emotional value is, the better the daywas. Bill suggests that the value of some period of human life is proportional to the sum of the emotional values of the days in the given period, multiplied by the smallest emotional value of the day in it. This schema reflects that good on average period can be greatly spoiled by one very bad day.
Now Bill is planning to investigate his own life and find the period of his life that had the greatest value. Help him to do so.
题目大意:
给出一个由n个数组成的数列a,问a[i]乘以以a[i]为最小值的一段连续序列的和最大是多少
AC代码:

struct node{    long long val;//值    long long l;//向左最多能扩展到哪个位置    long long r;//向右最多能扩展到哪个位置};node day[100010];long long sum[100010];//10万组数据,每个数据最大1e6,要防止爆intstack<node*> s;//要将指针入栈,而不是结构体的元素int main(){    int n;    cin >> n;//输入    for(int i = 1; i <= n; ++i)    {        scanf("%I64d",&day[i].val);        sum[i] = sum[i - 1] + day[i].val;//预处理前缀和    }    s.push(&day[1]);//将第一天的地址入栈    for(int i = 2; i <= n; ++i)    {        //注意判断非空要放在前面        while(!s.empty() && (*s.top()).val > day[i].val)//维护栈的单调性        {            (*s.top()).r = i - 1;            s.pop();//出栈        }        s.push(&day[i]);//入栈    }    while(!s.empty())//栈内的都是能向右扩展到位置n的    {        (*s.top()).r = n;        s.pop();    }    for(int i = n; i >= 1; --i)//反向来一次,就是向左最多能扩展到哪个位置    {        while(s.empty() == true)        {            s.push(&day[i]);            continue;        }        while(!s.empty() && (*s.top()).val > day[i].val)        {            (*s.top()).l = i + 1;            s.pop();        }        s.push(&day[i]);    }    while(!s.empty())    {        (*s.top()).l = 1;        s.pop();    }    long long ans = -inf,left,right,value;    for(int i = 1; i <= n; ++i)    {        value = day[i].val * (sum[day[i].r] - sum[day[i].l - 1]);//记录,防止重复计算,节省时间        if(value > ans)        {            ans = value;//更新            left = day[i].l;//记录位置            right = day[i].r;        }    }    printf("%I64d\n%I64d %I64d\n",ans,left,right);//打印    return 0;}

解决方法:
这道题是典型的单调栈的应用。转化一下,也就是解决以a[i]为最小值,向左右最多能扩展多少的问题。利用单调栈,可以将复杂度降为O(n)