牛客网 223C 区区区间间间(单调栈)

题目链接:区区区间间间

题意:给出长度为n的数字序列ai,定义区间(l,r)的价值为

请你计算出

题解:单调栈求ai左边和右边第一个比它小的位置,需要减去ai的个数为$(R_i-i+1)*(i-L_i+1)-1$。同理再用单调栈求ai左边和右边第一个比它大的位置,加上需要加上的ai个数即可。

解释1:需要减去的ai个数为$(R_i-i+1)*(i-L_i+1)-1$。

举个例子:1 2 3 4 5,求必须包含3的区间个数,左边有3种选择:1 2;2;不选;,右边也有三种选择:4 5;4;不选;但是题目中要求区间长度至少为2,所以两边都不选的情况不能计算在内。

解释2:为什么单调栈中一个a[i]<=a[st.top()],另一个是a[i]<a[st.top()](>=和>也同理)。

举个例子:5 6 5。这种情况很明显只有三个区间[5 6],[5 6 5],[6 5],即减去15。

但是如果直接用<=,那么每个位置对应的区间(li,ri)分别为[1,3],[2,2],[1,3]。减去20。可以发现[1,3]区间被减了两次,所以需要保证相等的时候一端扩展,避免重复计算。

stack:

 1 #include <stack>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <iostream>
 5 #include <algorithm>
 6 using namespace std;
 7 
 8 const int N=1e5+10;
 9 typedef long long ll;
10 stack <int> st;
11 ll l[N],r[N],a[N];
12 
13 int main(){
14     int t;
15     scanf("%d",&t);
16 
17     while(t--){
18         int n;
19         ll sum=0;
20         scanf("%d",&n);
21         for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
22         for(int i=1;i<=n;i++){
23             while(st.size()&&a[i]<=a[st.top()]) st.pop();
24             l[i]=st.size()==0?1:st.top()+1;
25             st.push(i);
26         }
27         while(st.size()) st.pop();
28         for(int i=n;i>=1;i--){
29             while(st.size()&&a[i]<a[st.top()]) st.pop();
30             r[i]=st.size()==0?n:st.top()-1;
31             st.push(i);
32         }
33         while(st.size()) st.pop();
34         for(int i=1;i<=n;i++) sum-=((r[i]-i+1)*(i-l[i]+1)-1)*a[i];
35         for(int i=1;i<=n;i++){
36             while(st.size()&&a[i]>=a[st.top()]) st.pop();
37             l[i]=st.size()==0?1:st.top()+1;
38             st.push(i);
39         }
40         while(st.size()) st.pop();
41         for(int i=n;i>=1;i--){
42             while(st.size()&&a[i]>a[st.top()]) st.pop();
43             r[i]=st.size()==0?n:st.top()-1;
44             st.push(i);
45         }
46         while(st.size()) st.pop();
47         for(int i=1;i<=n;i++) sum+=((r[i]-i+1)*(i-l[i]+1)-1)*a[i];
48         printf("%lld
",sum);
49     }
50 
51     return 0;
52 }
View Code
原文地址:https://www.cnblogs.com/pavtlly/p/10003420.html