​https://www.51nod.com/Challenge/Problem.html#!#problemId=1349​

单调栈找出最值区间 然后搞个后缀和就好了

要注意的是扩展区间时处理好同值的数 搞成左闭右开区间就好了

 

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e5+10;

stack <int> stk;
ll pre[maxn];
int ary[maxn],lef[maxn],rgt[maxn];
int n,q;

void init()
{
int i;
for(i=1;i<=n;i++){
while(!stk.empty()&&ary[stk.top()]<=ary[i]) stk.pop();
if(stk.empty()) lef[i]=1;
else lef[i]=stk.top()+1;
stk.push(i);
}
while(!stk.empty()) stk.pop();
for(i=n;i>=1;i--){
while(!stk.empty()&&ary[stk.top()]<ary[i]) stk.pop();
if(stk.empty()) rgt[i]=n;
else rgt[i]=stk.top()-1;
stk.push(i);
}
for(i=1;i<=n;i++) pre[ary[i]]+=(ll)(i-lef[i]+1)*(ll)(rgt[i]-i+1);
for(i=1e5;i>=1;i--) pre[i]+=pre[i+1];
}

int main()
{
int i,k;
scanf("%d",&n);
for(i=1;i<=n;i++) scanf("%d",&ary[i]);
init();
scanf("%d",&q);
while(q--){
scanf("%d",&k);
printf("%lld\n",pre[k]);
}
return 0;
}