题目大意:
一个数列,求对于每个ai右边有几个比它小的数,且这些比他小的数到ai之间没有比ai大的数。
思路:
问题可以很容易地转换为求右边第一个大于等于它的数的位置
然后就可以想到单调栈
有两种做法:
一:
从后向前走,栈内为单调递减,栈内元素需要记录一下它的值和位置,然后每个元素进来的时候弹出直到栈顶比该元素小,答案加上栈顶到现在位置的距离即可
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<algorithm> 5 #include<cstring> 6 #include<cstdlib> 7 #include<queue> 8 #include<vector> 9 #include<set> 10 #define inf 2147483611 11 #define ll long long 12 #define MAXN 80101 13 using namespace std; 14 inline int read() 15 { 16 int x=0,f=1; 17 char ch;ch=getchar(); 18 while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();} 19 while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();} 20 return x*f; 21 } 22 struct data 23 { 24 int pos,val; 25 }st[MAXN]; 26 int n,a[MAXN],top; 27 ll ans; 28 int main() 29 { 30 n=read(); 31 for(int i=1;i<=n;i++) a[i]=read(); 32 st[++top].val=inf,st[top].pos=n+1; 33 for(int i=n;i>=1;i--) 34 { 35 while(st[top].val<a[i]&&top) top--; 36 st[++top].pos=i,st[top].val=a[i]; 37 ans+=st[top-1].pos-i-1; 38 } 39 printf("%lld",ans); 40 }
二:
首先可以知道答案可以转化为每个点左边有几个比它大的数且之间没有更大的数则:
从前向后走,栈内为单调递减,栈内元素只需要记录一下它的值,然后对于每个点,我们弹出同上,答案只需要加上当前站内元素数,然后再把元素加入栈。
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<algorithm> 5 #include<cstring> 6 #include<cstdlib> 7 #include<queue> 8 #include<vector> 9 #include<set> 10 #define inf 2147483611 11 #define ll long long 12 #define MAXN 80101 13 using namespace std; 14 inline int read() 15 { 16 int x=0,f=1; 17 char ch;ch=getchar(); 18 while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();} 19 while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();} 20 return x*f; 21 } 22 int n,h,st[MAXN],top; 23 ll ans; 24 int main() 25 { 26 n=read(); 27 for(int i=1;i<=n;i++) 28 { 29 h=read(); 30 while(top&&st[top-1]<=h) top--; 31 ans+=top; 32 st[top++]=h; 33 } 34 printf("%lld",ans); 35 }