1. 程式人生 > >luogu1155 雙棧排序

luogu1155 雙棧排序

題目 所有 spa har col 嘗試 empty 進行 tor

題目大意

  運用兩個棧的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;
}

  

luogu1155 雙棧排序