基準時間限制: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;
}