洛谷 P3332 [ZJOI2013]K大數查詢
阿新 • • 發佈:2020-07-09
https://blog.csdn.net/lucky52529/article/details/89155694
單調棧的虛擬碼 stack<int> st; //此處一般需要給陣列最後新增結束標誌符,具體下面例題會有詳細講解 for (遍歷這個陣列) { if (棧空 || 棧頂元素大於等於當前比較元素) { 入棧; } else { while (棧不為空 && 棧頂元素小於當前元素) { 棧頂元素出棧; 更新結果; } 當前資料入棧; } }
也可以是這樣
單調棧的虛擬碼
先定義棧中是遞增 or 遞減。 for(){ while(){ pop();出棧 資料處理 } push(i);入棧 }
這個思想來自於
https://www.nowcoder.com/practice/2a2c00e7a88a498693568cef63a4b7bb?tpId=101&&tqId=33256&rp=1&ru=/ta/programmer-code-interview-guide&qru=/ta/programmer-code-interview-guide/question-ranking
題目描述
給定一個可能含有重複值的陣列 arr,找到每一個 i 位置左邊和右邊離 i 位置最近且值比 arr[i] 小的位置。返回所有位置相應的資訊。輸入描述:
第一行輸入一個數字 n,表示陣列 arr 的長度。
以下一行輸入 n 個數字,表示陣列的值
輸出描述:
輸出n行,每行兩個數字 L 和 R,如果不存在,則值為 -1,下標從 0 開始。示例1
輸入
複製7 3 4 1 5 6 2 7
輸出
複製-1 2 0 2 -1 -1 2 5 3 5 2 -1 5 -1
#include <vector> #include <iostream> #includeView Code<stack> #include <stdio.h> using namespace std; int main() { int n; scanf("%d",&n); vector<int>datas(n); vector<int>left_idx(n,-1); vector<int>right_idx(n,-1); stack<int>st; stack<int>st1; for(int i=0;i<n; i++){ scanf("%d",&datas[i]); } for(int i=0; i<n; i++){ while(!st.empty()&& datas[st.top()]>= datas[i]){ st.pop(); } if(!st.empty()){ left_idx[i] = st.top(); } st.push(i); } for(int i=n-1;i>=0;i--){ while(!st1.empty()&& datas[st1.top()]>= datas[i]){ st1.pop(); } if(!st1.empty()){ right_idx[i] = st1.top(); } st1.push(i); } for(int i=0;i<n;i++){ printf("%d %d\n", left_idx[i], right_idx[i]); } return 0; }
針對這個問題:
單調棧的應用我們直接拿一些具體的題來對照應用:
1.視野總和
描敘:有n個人站隊,所有的人全部向右看,個子高的可以看到個子低的髮型,給出每個人的身高,問所有人能看到其他人發現總和是多少。
輸入:4 3 7 1
輸出:2
解釋:個子為4的可以看到個子為3的髮型,個子為7可以看到個子為1的身高,所以1+1=2
#include<stdio.h> #include <iostream> #include<fstream> #include <stack> #include<vector> #include<limits.h> using namespace std; int fieldSum1(vector<int>&v); int fieldSum2(vector<int>&v); int main(){ int a[]={4,3,7,1}; vector<int> test(a,a+4); cout<<fieldSum1(test)<<endl; cout<<"-------"<<endl; cout<<fieldSum2(test)<<endl; cout<<"end"<<endl; return 0; } int fieldSum1(vector<int>&v){ stack<int>st; int sum=0; v.push_back(INI_MAX); for(int i=0; i<v.size();i++){ while(!st.empty() && v[st.top()] < v[i]){ int idx = st.top(); sum += (i-1-idx); st.pop(); } st.push(i); } return sum; } int fieldSum2(vector<int>& v) { v.push_back(INI_MAX); stack<int> st; int sum = 0; for (int i = 0; i < (int)v.size(); i++) { if (st.empty() || v[st.top()] > v[i])//小於棧頂元素入棧 { st.push(i); } else { while (!st.empty() && v[st.top()] <= v[i]) { int top = st.top();//取出棧頂元素 st.pop(); sum += (i - top - 1);//這裡需要多減一個1 } st.push(i); } } return sum; }