单调栈题单-15815Neat Tree

题目链接:https://ac.nowcoder.com/acm/problem/15815

题意:让求某个长度为n的数字序列中,所有连续子序列的最大值-最小值之和:\(\sum_{len=1}^{len=n}{Maxnum-Minnum}\)

思路:相当于计算a[i]作为最大值出现的次数-a[i]作为最小值出现的次数,也就是计算a[i]对于最后结果的贡献,由于是连续序列,O(n)时间复杂度中计算包含a[i]的连续序列中作为最小值或者最大值出现的次数,可以使用单调栈进行计算。注意:对于a[i],如果计算其作为最大值的次数,往左找到比a[i]值大的位置a[l],往右找到比a[i]值大的位置a[r],则构成的序列个数为(l-i+1)*(r-i+1)

代码:

#include<bits/stdc++.h>

using namespace std;
int a[(int)1e6+6];
int n;
int s[(int)1e6+5],w[(int)1e6+6];
long long  sta(int t){
    long long  ans=0;
    int tot=0;
    if(t){s[0]=0;a[n]=0;}
    else {s[0]=0x3f3f3f;a[n]=0x3f3f3f;}
    for(int i=0;i<=n;i++){
        int wd=1;//右边初始长度,即自身
        while(t==1 ? a[i]<s[tot]:a[i]>s[tot]){
            ans+=1LL*wd*s[tot]*w[tot];//注意此处:计算作为极值所处的连续子序列数目
            wd+=w[tot];
            tot--;
        }
        s[++tot]=a[i];w[tot]=wd;
    }
    return ans;
}
int main (){
    
    while(cin>>n){
    for(int i=0;i<n;i++){
        cin>>a[i];
    }
        cout<<sta(0)-sta(1)<<endl;
    }
    
    return 0;
}
上一篇:爬单个党建视频信息


下一篇:【ybt金牌导航4-2-1】【luogu P4169】[Violet]天使玩偶 / SJY摆棋子(K-D tree 模板)