淺談單調棧的實現方式和簡單應用


一、單調棧的原理和實現方式

1.定義

從棧底元素到棧頂元素呈單調遞增或單調遞減,棧內序列滿足單調性的棧;

2.原理

(1)當新元素在單調性上優於棧頂時(單增棧新元素比棧頂大,單減棧新元素比棧頂小),壓棧,棧深+1;

(2)當新元素在單調性與棧頂相同(新元素於棧頂相同)或劣於棧頂時(單增棧新元素比棧頂小,單減棧新元素比棧頂大),彈棧,棧深-1;

3.一般實現形式

以單增棧(棧頂為最大值)為例:

n為元素數,h為入棧序列,tot為棧深,stack為單增棧;

void stacks(){
        int stack[10001],tot=0,n,h;
        memset(stack,0,sizeof(stack));
        scanf("%d",&n);
        for(i=1;i<=n;++i){
                scanf("%d",&h);
                while(tot>0&&h<=stack[tot]) --tot;
                stack[++tot]=h;
        }
}

4.幾點注意

(1)在彈棧過程中,注意增加限制條件tot>0,若無此條件,如果新元素為負數,彈棧過程中就可能出現tot<0的現象;

(2)在彈棧壓棧過程中,注意隨時更新棧深;

(3)多次使用時沒必要每次都重置棧,有操作流程知數據直接覆蓋不會出現問題,可以節省時間;

二、相關應用

下面我們通過由簡到難介紹幾個題目來說明單調棧的使用方式:

1.[模板]最長上升子序列 (LIS)

Description

給一個數組 a[1],a[2],...,a[n],找到最長的上升子序列a[b1]< a[b2]< ... < a[bk]的長度,其中b[1]<b[2]< ... <b[k]。

Solution

1.用單調棧優化,利用LIS的單調性,使用單增棧,棧頂為最大值;

2.對於每一個數:

(1)當其大於棧頂時,滿足單調性,壓棧;

(2)當其小於棧頂時,不滿足單調性,向下搜索大於該數的最小值,替換;

(3)當其等於棧頂時,不滿足單調性,不作處理;

3.棧深即為LIS的長度;

Code

#include<cstdio>
#include<iostream>
#include<cmath>
#include<cstring> 
#include<algorithm>
using namespace std;

int a[1005],b[1005],n;
int stk[1005];

int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;i++) scanf("%d",&a[i]),b[i]=a[i];	
	sort(b+1,b+n+1);
	int tot=unique(b+1,b+n+1)-(b+1);
	for(int i=1;i<=n;i++) a[i]=lower_bound(b+1,b+tot+1,a[i])-b;
	int top=0;
	for(int i=1;i<=n;i++){
		if(top==0||stk[top-1]<a[i]) stk[top++]=a[i];
		else{
			*upper_bound(stk,stk+top,a[i])=a[i];
		}
	}
	printf("%d\n",top);
	return 0;	
}

2.[洛谷P1823]音樂會的等待

題解隨筆:http://www.cnblogs.com/COLIN-LIGHTNING/p/8486447.html

3.[POI 2008&洛谷P3467]PLA-Postering

題解隨筆:http://www.cnblogs.com/COLIN-LIGHTNING/p/8480054.html

4.[POJ 2559]Largest Rectangle in a Histogram

題解隨筆:http://www.cnblogs.com/COLIN-LIGHTNING/p/8480091.html

5.[洛谷P4147&BZOJ 3039]玉蟾宮

題解隨筆:http://www.cnblogs.com/COLIN-LIGHTNING/p/8480130.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM