zoukankan      html  css  js  c++  java
  • luogu1155 双栈排序

    题目大意

      运用两个栈的push和pop操作使得一个序列单调递增且操作字典序最小。$nleq 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
    ");
            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("
    ");
        return 0;
    }
    

      

  • 相关阅读:
    WPF 自定义NotifyPropertyChanged
    深度学习(五)正则化之L1和L2
    深度学习(三) 反向传播直观理解
    javascript中的原型和原型链(二)
    javascript中的原型和原型链(一)
    javascript中创建对象的方式及优缺点(二)
    javascript中创建对象的方式及优缺点(一)
    JS实现深拷贝的几种方法
    json.stringify()的妙用,json.stringify()与json.parse()的区别
    Javascript你必须要知道的知识点
  • 原文地址:https://www.cnblogs.com/headboy2002/p/9784750.html
Copyright © 2011-2022 走看看