【题意概述】
给出一个长度为n的序列a,求有多少对[i,j]满足i<j且a[i]>max(a[i+1],a[i+2],...,a[j]).
【题解】
单调栈。
倒着处理序列的元素,维护一个单调递减的栈,同时记录栈中的每个元素进栈的时间。如果当前元素x大于栈顶元素,那么栈顶到第二个元素在原素列之间的这一段就都是可以被x看见的,答案加上time[top]-time[top-1].
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 #define LL long long 5 #define rg register 6 #define N 200010 7 using namespace std; 8 LL n,top,cnt,a[N],s[N],time[N]; 9 LL ans; 10 inline LL read(){ 11 LL k=0,f=1; char c=getchar(); 12 while(c<'0'||c>'9')c=='-'&&(f=-1),c=getchar(); 13 while('0'<=c&&c<='9')k=k*10+c-'0',c=getchar(); 14 return k*f; 15 } 16 int main(){ 17 n=read(); 18 for(rg int i=1;i<=n;i++) a[i]=read(); 19 for(rg int i=1;i<=n;i++){ 20 LL x=a[n-i+1]; 21 while(s[top]<x&&top) ans+=time[top]-time[top-1],time[top--]=0; 22 if(s[top]!=x) s[++top]=x; 23 time[top]=i; 24 // printf("[%d %d]\n",top,ans); 25 // for(rg int j=1;j<=top;j++) printf("%d ",time[j]); puts(""); 26 } 27 printf("%lld\n",ans); 28 return 0; 29 }