51 Nod 1215 數組的寬度(單調棧)

題目來源: Javaman
基準時間限制:1 秒 空間限制:131072 KB 分值: 80 難度:5級算法題
 收藏
 關注
N個整數組成的數組,定義子數組a[i]..a[j]的寬度爲:max(a[i]..a[j]) - min(a[i]..a[j]),求所有子數組的寬度和。
Input
第1行:1個數N,表示數組的長度。(1 <= N <= 50000)
第2 - N + 1行:每行1個數,表示數組中的元素(1 <= A[i] <= 50000)
Output
輸出所有子數組的寬度和。
Input示例
5
1
2
3
4
5
Output示例
20

題解:求出每個數作爲最大值和最小值的範圍。開兩個棧,
    一個遞增,一個遞減。遞增的用來算ai的最小值範圍;
    遞減的來說最大值範圍。
#include <stdio.h>
#include <iostream>
#include <cstdlib>
#include <algorithm>
#include <cstring>
#include <stack>

using namespace std;
typedef long long ll;

const int maxn = 50010;

int n;
struct node
{
    int val;
    int i;
} a[maxn];

int main()
{
    freopen("test.in","r",stdin);
    while(~scanf("%d",&n))
    {
        ll ans=0;
        stack<node>sa,si;
        for(int i=1; i<=n; i++)
        {
            scanf("%d",&a[i].val);
            a[i].i=i;
        }
        for(int i=1; i<=n; i++)
        {
            if(sa.empty())
            {
                sa.push(a[i]);
            }
            else
            {
                node tem=sa.top();
                while(tem.val<a[i].val)
                {
                    sa.pop();
                    int x=0;
                    if(!sa.empty())
                        x=sa.top().i;
                    ans+=(ll)tem.val*((tem.i-x-1)*(i-tem.i-1)+i-x-1);
                    if(sa.empty())break;
                    tem=sa.top();
                }
                sa.push(a[i]);
            }

            if(si.empty())
            {
                si.push(a[i]);
            }
            else
            {
                node tem=si.top();
                while(tem.val>a[i].val)
                {
                    si.pop();
                    int x=0;
                    if(!si.empty())
                        x=si.top().i;
                    ans-=(ll)tem.val*((tem.i-x-1)*(i-tem.i-1)+i-x-1);
                    if(si.empty())break;
                    tem=si.top();
                }
                si.push(a[i]);
            }
        }
        while(!sa.empty())
        {
            node tem=sa.top();
            sa.pop();
            int x=0;
            if(!sa.empty())
                x=sa.top().i;
            ans+=(ll)tem.val*((tem.i-x-1)*(n-tem.i)+n-x);
        }
        while(!si.empty())
        {
            node tem=si.top();
            si.pop();
            int x=0;
            if(!si.empty())
                x=si.top().i;
            ans-=(ll)tem.val*((tem.i-x-1)*(n-tem.i)+n-x);
        }
        printf("%lld\n",ans);
    }
    return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章