单调栈(向右扩展)

https://blog.csdn.net/wcxyky/article/details/97617893?utm_source=app

1.给定一组数,针对每个数,寻找它和它左边第一个比它小的数之间有多少个数。

2.给定一序列,寻找某一子序列,使得子序列中的最小值乘以子序列的长度最大。

3.给定一序列,寻找某一子序列,使得子序列中的最小值乘以子序列所有元素和最大。

例题:http://poj.org/problem?id=3250

题意:有n头牛站一排且向右看,给出每条牛的高度,问每头牛可看到其他牛的头的总和和多少。

//#include<bits/stdc++.h>
#include<iostream>
#include<stdio.h>
#include<cstring>
#include<cmath>
using namespace std ;
typedef long long ll ;
const int N = 100010, M = 200010 ;
int r[N] , a[N];//找到右边第一个大于等于a[i]的数的下标
int n ;
int st[N] , top ;
void solve(){
    for(int i = 0 ; i < n ; i++){
        scanf("%d" , &a[i]);
    }
    top = 0 ; 
    for(int i = 0 ; i < n ; i++){
        while(top && a[st[top]] <= a[i]){
            r[st[top]] = i ;
            top--;
        }
        st[++top] = i ;
    }
    while(top){
        r[st[top]] = n ;
        top--;
    }
    ll ans = 0 ; 
    for(int i = 0 ; i < n ; i++){
        ans += r[i] - i - 1;//之间就是答案
    }
    cout << ans << endl;
}

signed main(){
    #ifdef ONLINE_JUDGE
	#else
		freopen("D:\c++\in.txt", "r", stdin);
		//freopen("D:\c++\out.txt", "w", stdout);
	#endif
    while(~scanf("%d" , &n))
        solve();
    
}
原文地址:https://www.cnblogs.com/nonames/p/12299953.html