「Luogu P1155」双栈排序

利用栈 \(s_1\) 和栈 \(s_2\) 将给出的数列排序,有以下四种操作,求出字典序最小的一种操作序列。

a :如果输入序列不为空,将第一个元素压入栈 \(s_1\)

b :如果栈 \(s_1\) 不为空, 将 \(s_1\) 栈顶元素弹出至输出序列

c :如果输入序列不为空,将第一个元素压入栈 \(s_2\)

d :如果栈 \(s_2\) 不为空,将 \(s_2\) 栈顶元素弹出至输出序列

Luogu

分析

一开始打了个 O(n) 的暴力贪心,然后成功的只拿到了 30pts ,后面看了题解才知道这道题居然用二分图染色做(果然是我太菜了吗)。

首先我们要建图,两个栈我们分别将染色为 1 和 -1 的元素弹入。存在 a[i] 和 a[j] 不能放在同一栈中的充要条件是存在 k ,使得 i < j < k ,a[i] < a[j] < a[k] 。然后我们将 i 和 j 连一条边。

然后开始染色。

最后模拟一遍即可。

(话说输出格式中的行尾没有空格是个假的吧......)

扫描二维码关注公众号,回复: 8646309 查看本文章

代码

//=========================
//  author:tyqs
//  date:2019.12.17
//  website:http://tyqs.kim
//=========================
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define N 1001
#define il inline
#define re register
#define tie0 cin.tie(0),cout.tie(0)
#define fastio ios::sync_with_stdio(false)
#define File(x) freopen(x".in","r",stdin);freopen(x".out","w",stdout)
using namespace std;
typedef long long ll;

template <typename T> inline void read(T &x) {
    T f = 1; x = 0; char c;
    for (c = getchar(); !isdigit(c); c = getchar()) if (c == '-') f = -1;
    for ( ; isdigit(c); c = getchar()) x = x * 10 + (c ^ 48);
    x *= f;
}

struct edge {
    int to, nxt;
} e[N<<1];

int n, t1, t2, l, cnt, now;
int a[N], col[N], s1[N], s2[N], head[N<<1];
char ans[N];
bool flg;

void insert(int u, int v) { e[++cnt] = (edge){v, head[u]}; head[u] = cnt; }

bool dfs(int u, int c) {
    col[u] = c;
    for (int i = head[u]; i; i = e[i].nxt) {
        int v = e[i].to;
        if (col[v] && col[u] != col[v]) continue;
        if (col[u] == col[v] || !dfs(v, -c)) return false;
    }
    return true;
}

int main() {
    read(n); now = 1;
    for (int i = 1; i <= n; ++i) read(a[i]);
    for (int i = 1; i < n; ++i)
        for (int j = i + 1; j < n; ++j)
            if (a[i] < a[j])
                for (int k = j + 1; k <= n; ++k)
                    if (a[k] < a[i]) insert(i, j), insert(j, i);
    for (int i = 1; i <= n; ++i)
        if (col[i] == 0)
            if (!dfs(i, 1)) flg = 1;
    if (!flg) {
        for (int i = 1; i <= n; ++i) {
            if (col[i] == 1) s1[++t1] = a[i], ans[++l] = 'a';
            else s2[++t2] = a[i], ans[++l] = 'c';
            while ((s1[t1] == now && t1) || (s2[t2] == now && t2)) {
                if (s1[t1] == now && t1) t1--, now++, ans[++l] = 'b';
                else t2--, now++, ans[++l] = 'd';
            }
        }
        for (int i = 1; i <= l; ++i) printf("%c ", ans[i]);
    }
    else puts("0");
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/hlw1/p/12202821.html