luogu1155 双栈排序

题目大意

  运用两个栈的push和pop操作使得一个序列单调递增且操作字典序最小。$n\leq 1000$。

题解

  本题我们要尝试运用“瞪眼法”,也就是推样例。我们显然要数字尽可能地推入第一个栈。那么问题就是:怎样的两个数字不可以在同一个栈中呢?这样的效果是:当一个数字a想要出栈时,其上端有个被他大的数字b挡着,且是不得不挡着。怎么会“不得不”呢?那是因为有一个数字c<a在b的上面(原序列中,c在b的右面),因为要想使输出序列递增,必须把b入了栈以后才能出栈。所以,a和c不能共存。将所有满足a、c这样的条件的点连边,进行二分图染色(进入栈的编号)(染不了色输出-1),然后模拟即可。

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <stack>
#include <vector>
using namespace std;

const int MAX_NODE = 1010, MAX_EDGE = MAX_NODE * MAX_NODE;
vector<char> Ops;

struct Node;
struct Edge;

struct Node
{
    Edge *Head;
    int Color;
}_nodes[MAX_NODE];
int TotNode;
Node *A[MAX_NODE];
stack<Node*> St[3];

struct Edge
{
    Node *To;
    Edge *Next;
}_edges[MAX_EDGE];
int _eCount;

void Dfs(Node *cur, int color)
{
    if (cur->Color && cur->Color != color)
    {
        printf("0\n");
        exit(0);
    }
    if (cur->Color)
        return;
    cur->Color = color;
    for (Edge *e = cur->Head; e; e = e->Next)
        Dfs(e->To, color == 1 ? 2 : 1);
}

void AddEdge(Node *from, Node *to)
{
    Edge *e = _edges + ++_eCount;
    e->To = to;
    e->Next = from->Head;
    from->Head = e;
}

void Build(Node *u, Node *v)
{
    AddEdge(u, v);
    AddEdge(v, u);
}

void BuildGraph()
{
    static Node *AftMinV[MAX_NODE];
    AftMinV[TotNode] = A[TotNode];
    for (int i = TotNode - 1; i >= 1; i--)
        AftMinV[i] = min(A[i], AftMinV[i + 1]);
    for (int i = 1; i <= TotNode; i++)
        for (int j = i + 1; j <= TotNode; j++)
            if (A[i] < A[j] && AftMinV[j] < A[i])
                Build(A[i], A[j]);
}

int main()
{
    scanf("%d", &TotNode);
    for (int i = 1; i <= TotNode; i++)
    {
        int vId;
        scanf("%d", &vId);
        A[i] = _nodes + vId;
    }
    BuildGraph();
    for (int i = 1; i <= TotNode; i++)
        if (!A[i]->Color)
            Dfs(A[i], 1);
    Node *cur = _nodes + 1;
    for (int i = 1; i <= TotNode; i++)
    {
        Ops.push_back(A[i]->Color == 1 ? 'a' : 'c');
        St[A[i]->Color].push(A[i]);
        while (!St[cur->Color].empty() && St[cur->Color].top() == cur)
        {
            St[cur->Color].pop();
            Ops.push_back(cur->Color == 1 ? 'b' : 'd');
            cur++;
        }
    }
    for (unsigned int i = 0; i < Ops.size(); i++)
        printf("%c ", Ops[i]);
    printf("\n");
    return 0;
}

  

posted @ 2018-10-13 23:23  headboy2002  阅读(159)  评论(0编辑  收藏  举报