1. 程式人生 > >【資料結構】單調棧

【資料結構】單調棧

  • 基本介紹
  • 模板題目
  • 程式碼實現

基本介紹

之前沒有寫過棧 棧是隻能在某一端插入和刪除的特殊線性表 就像一個桶一樣 我們可以用STL 也可以自己寫
進棧 top++ 然後 _stack[top]=進棧元素
退棧 可以將退棧後的一個元素賦值到一個地方 top–

單調棧 故名思議 就是多了個 單調 的要求
(以下文字引用於Shuyu Fang的部落格)
若是單調遞增棧 則從棧頂到棧底的元素是嚴格遞增的 若是單調遞減棧 則從棧頂到棧底的元素是嚴格遞減的 越靠近棧頂的元素越後進棧
元素進棧過程: 對於單調遞增棧 若當前進棧元素為e 從棧頂開始遍歷元素 把小於e或者等於e的元素彈出棧 直接遇到一個大於e的元素或者棧為空為止 然後再把e壓入棧中 對於單調遞減棧 則每次彈出的是大於e或者等於e的元素

模板題目

洛谷p1901 發射站
題目描述
某地有 N 個能量發射站排成一行,每個發射站 i 都有不相同的高度 Hi,並能向兩邊(當 然兩端的只能向一邊)同時發射能量值為 Vi 的能量,並且發出的能量只被兩邊最近的且比 它高的發射站接收。
顯然,每個發射站發來的能量有可能被 0 或 1 或 2 個其他發射站所接受,特別是為了安 全,每個發射站接收到的能量總和是我們很關心的問題。由於資料很多,現只需要你幫忙計 算出接收最多能量的發射站接收的能量是多少。

輸入輸出格式
輸入格式:
第 1 行:一個整數 N;
第 2 到 N+1 行:第 i+1 行有兩個整數 Hi 和 Vi,表示第 i 個人發射站的高度和發射的能量值。
輸出格式:
輸出僅一行,表示接收最多能量的發射站接收到的能量值,答案不超過 longint。

輸入輸出樣例
輸入樣例:
3
4 2
3 5
6 10
輸出樣例:
7

題解中有講解

程式碼實現



3
4 2
3 5
6 10
#include<iostream>
#include<cstdio>
#include<cctype>
#include<algorithm>

using namespace std;
#define ll long long
#define in =read()
const int size = 1000000 + 50;
ll _stack[size],pos[size],b[size]; 
ll n,top,ans;

struct
data{ ll h,v; }a[size]; inline ll max(ll x,ll y) { return x>y?x:y; } inline ll read() { ll num=0,f=1; char ch=getchar(); while(!isdigit(ch)){ if(ch=='-') f=-1; ch=getchar(); } while(isdigit(ch)){ num=num*10+ch-'0'; ch=getchar(); } return num*f; } inline void f (int x) { while(top&&_stack[top]<=a[x].h) top--; b[pos[top]]+=a[x].v; _stack[++top]=a[x].h; pos[top]=x; cout<<b[top]<<" "<<_stack[top]<<" "<<pos[top]<<endl; } int main() { int i; n in; for(i=1;i<=n;i++){ a[i].h in; a[i].v in; } for(i=1,top=0;i<=n;i++) f(i); for(i=n,top=0;i;i--) f(i); /* for(int i=0;i<=n;i++) { cout<<b[i]<<" "<<_stack[i]<<" "<<pos[i]; cout<<endl; }*/ for(i=1;i<=n;i++) ans=max(ans,b[i]); printf("%d",ans); } //COYG