codevs 1170 双栈排序

/*
好题啊 好题啊
而然还是看了一眼题解啊
有那么一点思路 但是离写出代码还很远
考虑必须分开放倒两个栈里的情况
即存在i<j<k 有 a[k]<a[i]<a[j] 这里RMQ n*n搞一下 
那如果出现 a b 不在一块 b c 不在一块 a c 不在一块
那么两个栈显然办不了了
所以嘛 因为只有俩栈 染色吧那就
染完判一下输出0的情况
同时不相邻的那些的块块 按字典序染
然后就就模拟一下 就像个普通的火车进站类似的题
只不过有两个栈
注意当可以进2出1的时候 先出1 这样字典序小 
(感觉到了字典序深深地恶意) 
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#define maxn 1010
using namespace std;
int n,m,a[maxn],num,head[maxn],color[maxn],mx[maxn][25],P[maxn],falg;
int s1[maxn],top1,s2[maxn],top2;
struct node{
    int v,pre;
}e[maxn*maxn*2];
int max(int x,int y){
    return x>y?x:y;
}
void Add(int from,int to){
    num++;e[num].v=to;
    e[num].pre=head[from];
    head[from]=num;
}
void Insert(){
    memset(mx,127/3,sizeof(mx));
    for(int i=1;i<=n;i++)mx[i][0]=a[i];
    for(int j=1;j<=20;j++)
        for(int i=1;i+(1<<j)-1<=n;i++)
            mx[i][j]=min(mx[i][j-1],mx[i+(1<<j-1)][j-1]);
}
void Get(){
    for(int i=1;i<=n;i++)
        for(int j=0;j<=20;j++)
            if((1<<j)>i){
                P[i]=j-1;break;
            }
}
int Query(int l,int r){
    int k=P[r-l+1];
    return min(mx[l][k],mx[r-(1<<k)+1][k]);
}
int Dfs(int x){
    for(int i=head[x];i;i=e[i].pre){
        int v=e[i].v;
        if(color[v]==0){
            color[v]=3-color[x];
            if(!Dfs(v))return 0;
        }
        else if(color[v]==color[x])return 0;
    }
    return 1;
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%d",&a[i]);
    Insert();Get();
    for(int i=1;i<=n;i++)
        for(int j=i+1;j<=n;j++){
            if(a[i]>a[j])continue;
            int mx=Query(j+1,n);
            if(mx<a[i])Add(a[i],a[j]),Add(a[j],a[i]);
        }
    for(int i=1;i<=n;i++)
        if(color[i]==0){
            color[i]=1;
            if(!Dfs(i)){falg=1;break;}
        }
    if(falg==1){printf("0
");return 0;}
    int now=1;
    for(int i=1;i<=n;i++){
        if(color[a[i]]==1){
            if(a[i]==now){printf("a b ");now++;}
            else{
                while(a[i]>s1[top1]&&top1){
                    top1--;printf("b ");
                }
                s1[++top1]=a[i];printf("a ");
            }
        }
        else {
            if(a[i]==now){printf("c d ");now++;}
            else{
                while(a[i]>s2[top2]&&top2){
                    top2--;printf("b ");
                }
                while(s1[top1]==now){
                    top1--;printf("b ");now++;
                }
                s2[++top2]=a[i];printf("c ");
            }
        }
    }
    for(int i=now;i<=n;i++){
        while(top1&&i==s1[top1]){
            top1--;printf("b ");
        }
        while(top2&&i==s2[top2]){
            top2--;printf("d ");
        }
    }
    return 0;
}
原文地址:https://www.cnblogs.com/yanlifneg/p/5947445.html