洛谷P1155 双栈排序

题目

通过观察可以发现,直接考虑双栈比较困难,考虑单栈的情况;
不难发现,如果当序列中出现A小于B,A大于C(A在B前面,B在C前面),A和B就不能在同一个栈里;
这样,我们就有了一堆在与不在同一个集合的关系;我们可以通过二分图染色或带偏移量的并查集;
这样我们可以预处理出每一个A的最后一个C,然后和其中的每一个B都连一条边;跑一个二分图染色,优先把点放入0号集合;无解,输出0;有解,我们已经知道方案了,直接模拟一波就好;from

标程:

#include<bits/stdc++.h>
using namespace std;
const int N=1002;
struct node{
    int to,ne;
}e[N];
int vis[N],h[N],col[N],st1[N],st2[N],cur,i,j,b[N],a[N],tot,n,cnt1,cnt2;
inline char gc(){
    static char buf[100000],*p1=buf,*p2=buf;
    return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
#define gc getchar
inline int read(){
    int x=0,fl=1;char ch=gc();
    for (;ch<48||ch>57;ch=gc())if(ch=='-')fl=-1;
    for (;48<=ch&&ch<=57;ch=gc())x=(x<<3)+(x<<1)+(ch^48);
    return x*fl;
}
void add(int x,int y){
    e[++tot]=(node){y,h[x]};
    h[x]=tot;
}
bool dfs(int u){
    vis[u]=1;
    for (int i=h[u],v;i;i=e[i].ne)
        if (!vis[v=e[i].to]){
            col[v]=col[u]^1;
            if (!dfs(v)) return 0;
        }
        else if (col[v]==col[u]) return 0;
    return 1;
}
int main(){
    n=read();
    for (i=1;i<=n;i++) a[i]=read();
    for (i=1;i<=n;i++)
        for (j=n;j>i;j--)
            if (a[j]<a[i]){
                b[i]=j;
                break;
            }
    for (i=1;i<=n;i++)
        for (j=i+1;j<b[i];j++)
            if (a[i]<a[j]) add(i,j),add(j,i);
    for (i=1;i<=n;i++)
        if (!vis[i])
            if (!dfs(i)){
                putchar('0');
                return 0;
            }
    cur=1;
    for (i=1;i<=n;i++){
        if (!col[i]) printf("a "),st1[++cnt1]=a[i];
        else printf("c "),st2[++cnt2]=a[i];
        while (st1[cnt1]==cur || st2[cnt2]==cur){
            if (st1[cnt1]==cur) printf("b "),cnt1--;
            else printf("d "),cnt2--;
            cur++;
        }
    }
    while (st1[cnt1]==cur || st2[cnt2]==cur){
        if (st1[cnt1]==cur) printf("b "),cnt1--;
        else printf("d "),cnt2--;
        cur++;
    }
}

猜你喜欢

转载自blog.csdn.net/xumingyang0/article/details/80602243