首页 > 代码库 > codevs 1170 双栈排序

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 1010using 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\n");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;}

 

codevs 1170 双栈排序