【noip2008】雙棧排序

參考神仙的博客

如下是我對正確性的一些解釋c++

因爲元素按順序進棧,因此咱們要保證在前面的字典序儘量小,因此優先讓先進棧的進棧1,進不了棧1才進棧2,故兩個棧中的元素是惟一肯定的spa

  1. 因爲咱們須要按必定順序入棧,故入棧順序顯然是必定的,即a,c相對順序必定
  2. 因爲咱們對元素進行了排序,故出棧的相對順序是必定的,即b,d相對順序必定
  3. 根據yxc老師的證實,若是隻有一個棧,那麼進出棧順序是必定的,即a,b相對順序和c,d相對順序必定

可是b,c的相對順序和a,d的相對順序是不肯定的code

b,c對應出棧1,入棧2,因爲咱們在代碼中能出棧就出棧,因此字典序是正確的blog

a,d對應入棧1,出棧2,因爲咱們在代碼中能出棧就出棧,因此會輸出d,a,而實際上a,d是更優的排序

因此咱們只須要在不改變上述肯定的相對順序的前提下交換d,a便可,即交換全部相鄰的d,aip

代碼以下,歡迎hack

#include<bits/stdc++.h>
using namespace std;

#define go(i,a,b) for(int i=a;i<=b;++i)
#define com(i,a,b) for(int i=a;i>=b;--i)
#define mem(a,b) memset(a,b,sizeof(a))
#define fo(i,a) for(int i=0;i<a;++i)
#define il inline

const int inf=0x3f3f3f3f,N=1010;

int n,a[N],suf[N],co[N],tot;
bool g[N][N];
char ans[N*2];

bool dfs(int u,int c){
    co[u]=c;
    go(i,1,n){
        if(!g[u][i]) continue;
        if(co[i]==c) return 0;
        if(!co[i]&&!dfs(i,3-c)) return 0;
    }
    return 1;
}

void solve(){
    stack<int>s1,s2;
    int now=1;
    go(i,1,n){
        if(co[i]==1){
            s1.push(a[i]);
            ans[++tot]='a';
        }
        else{
            s2.push(a[i]);
            ans[++tot]='c';
        }
        while(1){
            if(!s1.empty()&&s1.top()==now) s1.pop(),ans[++tot]='b',++now;
            else if(!s2.empty()&&s2.top()==now) s2.pop(),ans[++tot]='d',++now;
            else break;
        }
    }
    go(i,1,tot)
        if(ans[i]=='a'&&ans[i-1]=='d')
            swap(ans[i],ans[i-1]);
}

int main(){
    //freopen("input.txt","r",stdin);
    cin>>n;
    go(i,1,n) scanf("%d",a+i);
    suf[n+1]=inf;
    com(i,n,1) suf[i]=min(suf[i+1],a[i]);
    go(i,1,n)
        go(j,i+1,n){
            if(a[i]<a[j]&&suf[j+1]<a[i]) g[i][j]=g[j][i]=1;
        }
    go(i,1,n){
        if(!co[i]&&!dfs(i,1)){
            puts("0");
            return 0;
        }
    }
    solve();
    go(i,1,tot) printf("%c ",ans[i]);
    return 0;
}
相關文章
相關標籤/搜索