1845: 凹(New Online Judge)
题目描述
给定一个长度为n的数组a,请求出存在多少个二元组<i,j>满足“凹”的性质:
1、1≤i<j≤n;
2、对于所有的i<k<j均满足a[i]>a[k],a[j]>a[k]。
注意,当j=i+1时,k不存在,也满足上述约束。
输入
第一行为正整数n,n≤1000000。
接下来n行,每行一个a[i],1≤a[i]≤n,a[i]不互相同。
输出
输出一个数字表示答案。
样例输入
样例1:
3
2
1
3
样例2:
6
1
3
2
6
4
5
样例输出
样例1:
3
样例2:
7
题解1(C++版本)
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 1e6 + 10;
int n, a[N], st[N], top = -1, L[N], R[N];
int main(){
LL ans = 0; //最终答案可能超出int类型的最大值
scanf("%d", &n);
for(int i = 1; i <= n; i++){
scanf("%d", &a[i]);
}
//从左到右构建一个递减的单调栈
for(int i = 1; i <= n; i++){
while(top != -1 && a[st[top]] < a[i]){
L[st[top]] = i; //右边第一个大于它的元素下标
top--;
}
st[++top] = i;
}
//从右到左构建一个递减的单调栈
for(int i = n; i > 0; i--){
while(top != -1 && a[st[top]] < a[i]){
R[st[top]] = i; //左边第一个大于它的元素下标
top--;
}
st[++top] = i;
}
for(int i = 1; i <= n; i++){
if(L[i] && R[i]) ans++;
}
printf("%lld\n", ans + n - 1); // n - 1表示相邻两个元素算一次 ,n个元素共(n-1)次
return 0;
}