棧和排序(csdn一大堆水題解,我自己出一個吧,)後綴維護+模擬

棧和排序

在這裏插入圖片描述

題意:

給你一個入棧排列,要你求字典序最大的出棧序列。

思路:

最先想到的:最先出的肯定是n。(它最大,肯定要在最前面)

反思x1:

我一開始想的時候走遠了。錯誤示範:以爲找到最大n後,就看棧頂和後面的。如果後面有次大就,其它直接入棧直到找到次大。如果次大在前面,就把大於待入棧元素x的棧頂元素先出棧,其實這種思路是錯的,假如次大是第一個入棧,那麼無論如何都會去 “如果次大在前面,就把大於待入棧元素x的棧頂元素先出棧”,這種情況,假如把棧頂元素出棧了,那麼可能後面待入棧元素有更大的,就矛盾了。

所以引進第二種思路,

下文中的待入棧元素指的是輸入,(以用紅色標出)
下文中的指的是爲解決問題定義的棧。

  1. 對於找到最大後。
  2. 考察頂元素和待入棧元素中的最大(要0n的查詢後面待入棧元素的最大)
  3. 如果頂元素比後面的都大(比待入棧元素的最大 大,那麼肯定比後面的都大)那麼頂元素出,重複步驟3,直到不滿足。
  4. 3不滿足來到4。直到找到待入棧元素的最大,其他都入
  5. 之後重複步驟2
  6. 當沒有待入棧元素時,把內元素出就行了。

AC(數據1e3)

#include <iostream>
#include <stack>
#include <queue>
#define For(i,x,y) for(register int i=(x); i<=(y); i++)
using namespace std;
stack<int>st;
int n,vis[300],x,maxx;
int main()
{
    ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    cin>>n;
    For(i,1,n)
    {
        cin>>x;
        maxx=0;
        For(i,1,n)if(!vis[i])maxx=max(i,maxx);
        //沒見過的元素,就是待入棧元素
        while(!st.empty()&&maxx<st.top())
        {
            cout<<st.top()<<' ';st.pop();
        }
        st.push(x);
        vis[x]=1;//cout<<i<<endl;
    }
    while(!st.empty())
    {
        cout<<st.top()<<' ';
        st.pop();
    }
    return 0;
}


反思x2:

很明顯,上面的代碼,當數據量很大時,是會tle的,因爲第2步中0n的查詢

優化方法:

也很簡單,對於待入棧元素,就是後面的元素中的最大值,那麼可以用一個suf【】(後綴去預處理位置 i 以後的最大值)

AC(數據1e6)

#include <iostream>
#include <stack>
#include <queue>
#define For(i,x,y) for(register int i=(x); i<=(y); i++)
using namespace std;
const int maxn=1e5+10;
stack<int>st;
int n,x,a[maxn],suf[maxn];//,pre[maxn]maxx,vis[maxn],t,
int main()
{
    ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    cin>>n;
    For(i,1,n)cin>>a[i];
    for(int i=n; i>=1; i--)
    {
        if(a[i]>suf[i+1])suf[i]=a[i];
        else suf[i]=suf[i+1];
    }
    For(i,1,n)
    {
        x=a[i];
        while(!st.empty()&&suf[i]<st.top())
        //suf【i】就是優化,省了0n查詢
        {
            cout<<st.top()<<' ';st.pop();
        }
        st.push(x);
    }
    while(!st.empty())//把剩下的輸出
    {
        cout<<st.top()<<' ';
        st.pop();
    }
    return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章