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\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;
}
时间: 2024-08-03 07:17:09

codevs 1170 双栈排序的相关文章

双栈排序(codevs 1170)题解

[问题描述] Tom最近在研究一个有趣的排序问题.如图所示,通过2个栈S1和S2,Tom希望借助以下4种操作实现将输入序列升序排序. 操作a 如果输入序列不为空,将第一个元素压入栈S1 操作b 如果栈S1不为空,将S1栈顶元素弹出至输出序列 操作c 如果输入序列不为空,将第一个元素压入栈S2 操作d 如果栈S2不为空,将S2栈顶元素弹出至输出序列 如果一个1~n的排列P可以通过一系列操作使得输出序列为1,2,…,(n-1),n,Tom就称P是一个“可双栈排序排列”.例如(1,3,2,4)就是一个

Noip2008双栈排序

[问题描述] 用两个栈使一个1...n的排列变得有序.一共有四个操作: A.stack1.push() 读入一个放入栈一 B.stack1.pop() 弹出栈一放入输出序列 C.stack2.push() 读入一个放入栈二 D.stack2.pop() 弹出栈二放入输出序列 给你一个初始的排列,求一个字典序最小的操作序列使得变得有序,若没有满足条件的操作序列,输出'0'. Sample.in                                Sample.out 4     1 3

AC日记——双栈排序 洛谷 P1155

双栈排序 思路: 二分图染+模拟: 代码: #include <bits/stdc++.h> using namespace std; #define maxn 1005 #define maxm 2000005 int n,head[maxn],E[maxm],V[maxm],cnt,col[maxn]; int minn[maxn],ai[maxn],sta1[maxn],sta2[maxn],top1,top2; bool if_[maxn][maxn]; inline void in(

NOIP2008 双栈排序

题目描述 Tom最近在研究一个有趣的排序问题.如图所示,通过2个栈S1和S2,Tom希望借助以下4种操作实现将输入序列升序排序. 操作a 如果输入序列不为空,将第一个元素压入栈S1 操作b 如果栈S1不为空,将S1栈顶元素弹出至输出序列 操作c 如果输入序列不为空,将第一个元素压入栈S2 操作d 如果栈S2不为空,将S2栈顶元素弹出至输出序列 如果一个1~n的排列P可以通过一系列操作使得输出序列为1,2,…,(n-1),n,Tom就称P是一个“可双栈排序排列”.例如(1,3,2,4)就是一个“可

BZOJ 2080: [Poi2010]Railway 双栈排序

2080: [Poi2010]Railway Time Limit: 10 Sec  Memory Limit: 259 MBSubmit: 140  Solved: 35[Submit][Status][Discuss] Description 一个铁路包含两个侧线1和2,右边由A进入,左边由B出去(看下面的图片) 有n个车厢在通道A上,编号为1到n,它们被安排按照要求的顺序(a1,a2,a3,a4....an)进入侧线,进去还要出来,它们要按照编号顺序(1,2,3,4,5....n)从通道B

二分图 and code1170 双栈排序

6.6二分图 二分图是这样一个图: 有两顶点集且图中每条边的的两个顶点分别位于两个顶点集中,每个顶点集中没有边直接相连接. 无向图G为二分图的充分必要条件是,G至少有两个顶点,且其所有回路的长度均为偶数. 判断二分图的常见方法是染色法: 开始对任意一未染色的顶点染色,之后判断其相邻的顶点中,若未染色则将其染上和相邻顶点不同的颜色, 若已经染色且颜色和相邻顶点的颜色相同则说明不是二分图,若颜色不同则继续判断,bfs和dfs都可以. 易知:任何无回路的的图均是二分图. 代码: bool Color(

NOIP2008 双栈排序 染色+模拟

挺不错的一道题,首先可以知道若存在形如 k<i<j 但 a[k]<a[i]<a[j]这样的,那么i,j一定不能(从始至终不能)进入同一个栈 例如 2 3 1,若2 3进入同一个栈,那么1再进栈然后马上出栈,这时候,2没有办法在3之前出来. 所以对于这样的i,j我们连一条边,然后dfs染色,若染色中发现相邻点颜色相同,则无解,否则我们按照1,2,1,2的顺序染色. 确定了每一个数属于哪个栈后,用2个stack模拟一下就好了. #include <iostream> #in

洛谷——P1155 双栈排序

题目描述 Tom最近在研究一个有趣的排序问题.如图所示,通过2个栈S1和S2,Tom希望借助以下4种操作实现将输入序列升序排序. 操作a 如果输入序列不为空,将第一个元素压入栈S1 操作b 如果栈S1不为空,将S1栈顶元素弹出至输出序列 操作c 如果输入序列不为空,将第一个元素压入栈S2 操作d 如果栈S2不为空,将S2栈顶元素弹出至输出序列 如果一个1~n的排列P可以通过一系列操作使得输出序列为1,2,…,(n-1),n,Tom就称P是一个“可双栈排序排列”.例如(1,3,2,4)就是一个“可

P1155 双栈排序

P1155 双栈排序 题目描述 Tom最近在研究一个有趣的排序问题.如图所示,通过2个栈S1和S2,Tom希望借助以下4种操作实现将输入序列升序排序. 操作a 如果输入序列不为空,将第一个元素压入栈S1 操作b 如果栈S1不为空,将S1栈顶元素弹出至输出序列 操作c 如果输入序列不为空,将第一个元素压入栈S2 操作d 如果栈S2不为空,将S2栈顶元素弹出至输出序列 如果一个1~n的排列P可以通过一系列操作使得输出序列为1,2,-,(n-1),n,Tom就称P是一个"可双栈排序排列".例