描述
Given a sequence, we define the seqence's value equals the difference between the largest element and the smallest element in the sequence. As an example, the value of sequence (3, 1, 7, 2) = 7-1 = 6.
Now, given a sequence S, output the sum of all value of consecutive subsequences.
输入
The first line has an integer N (2 ≤ N ≤ 300000) indicating the number of elements of the sequence. Then follows N lines, each line has a positive integer no larger than 108 indicating an element of the sequence.
输出
Output the requested sum.
样例输入
4
3
1
7
2
样例输出
31
提示
The consecutive subsequence of the sequence (3, 1, 7, 2) has:
(3, 1), (1, 7), (7, 2), (3, 1, 7), (1, 7, 2), (3, 1, 7, 2)
The sum of all values equals 2+6+5+6+6+6=31
题意
求所有区间极差和
题解
N很大,考虑单调栈维护max和min,那么就是求ans=Σmax-Σmin
sum1代表最大值前缀和
sum2代表最小值前缀和
max单调栈,d[i]代表下标,b[i]代表值,tail1代表栈顶
min单调栈,e[i]代表下标,c[i]代表值,tail2代表栈顶
考虑加入一个a的贡献,sum1+=(d[tail1]-d[tail1-1])*a-弹出的Σ(d[tail1]-d[tail1-1])*b[tail1],sum2+=(e[tail2]-e[tail2-1])*a-弹出的Σ(e[tail2]-e[tail2-1])*c[tail2],就是计算后的sum1-sum2
代码
#include<stdio.h> #define ll __int64 const int N=3e5+5; int n,a[N],b[N],c[N],d[N],e[N]; ll ans,sum1,tail1,sum2,tail2; int main() { scanf("%d",&n); for(int i=1;i<=n;i++)scanf("%d",&a[i]); for(int i=1;i<=n;i++) { while(1<=tail1&&b[tail1]<=a[i]) { sum1-=(d[tail1]-d[tail1-1])*1LL*b[tail1]; tail1--; } while(1<=tail2&&c[tail2]>=a[i]) { sum2-=(e[tail2]-e[tail2-1])*1LL*c[tail2]; tail2--; } b[++tail1]=a[i];d[tail1]=i; c[++tail2]=a[i];e[tail2]=i; sum1+=(d[tail1]-d[tail1-1])*1LL*a[i]; sum2+=(e[tail2]-e[tail2-1])*1LL*a[i]; ans+=sum1-sum2; } printf("%I64d ",ans); return 0; }