PQ 树

PQ 树

  • 算是 oi-wiki 的感性理解吧

76f942b4b0de8fcf5b399bcaa0458867

90fa4718263445d41e84d8b837b40ef7

ae4348315a17405c3a2b958bdd3e50eb

参考实现

#include <bits/stdc++.h>
using namespace std;
void Fail() { cout << "NO" << '\n';exit(0); }
struct PQT
{
    enum co { white = 0, black = 1, gray = 2 };
    enum node { P = 0, Q = 1 };
    vector<int> bin;
    vector<vector<int>> G;
    vector<co> col;
    vector<node> tp;
    string s;
    int n, idx;
    vector<int> Rev(vector<int> y) { reverse(y.begin(), y.end());return y; }
    void Merge(vector<int>& x, vector<int> y) { x.insert(x.end(), y.begin(), y.end()); }
    int newnode(node v)
    {
        int res; if (bin.empty())res = ++idx;
        else res = bin.back(), bin.pop_back();
        tp[res] = v; G[res].clear(); return res;
    }
    void del(int x) { bin.push_back(x); }
    void build(const int _n)
    {
        n = _n;idx = n + 1;
        bin.clear();
        G.resize(n * 3 + 3);
        col.resize(n * 3 + 3);
        tp.resize(n * 3 + 3);
        for (int i = 1;i <= n;i++)
            G[n + 1].push_back(i);
        tp[n + 1] = P;
    }
    void dfscol(int x)
    {
        if (1 <= x && x <= n) col[x] = co(s[x - 1] == '1');
        else
        {
            bool a = false, b = false;
            for (int v : G[x])
            {
                dfscol(v);
                if (col[v] == white)a = true;
                else if (col[v] == black)b = true;
                else a = b = true;
            }
            if (a && b)col[x] = gray;
            else if (a)col[x] = white;
            else col[x] = black;
        }
    }
    void remove(int x) { for (auto& v : G[x]) { while (G[v].size() == 1) del(v), v = G[v][0];remove(v); } }
    bool check(vector<int>& x)
    {
        int ps = -1;
        for (int i = 0;i < x.size();i++)if (col[x[i]] == gray)ps = i;
        if (ps == -1) { for (int i = 0;i < x.size();i++)if (col[x[i]] == black) { ps = i;break; } }
        for (int i = 0;i < ps;i++)if (col[x[i]] != white)return false;
        for (int i = ps + 1;i < x.size();i++)if (col[x[i]] != black)return false;
        return true;
    }
    vector<int> split(int x)
    {
        if (col[x] != gray)return { x };
        if (tp[x] == Q)
        {
            if (!check(G[x]))G[x] = Rev(G[x]);
            if (!check(G[x]))Fail();
            vector<int> res;
            for (int v : G[x])
            {
                if (col[v] == gray)Merge(res, split(v));
                else res.push_back(v);
            }
            del(x); return res;
        }
        else
        {
            vector<int> s[3], res; int t;
            for (int v : G[x])s[col[v]].push_back(v);
            if (s[gray].size() >= 2)Fail();
            if (s[white].size())t = newnode(P), G[t] = s[white], res.push_back(t);
            if (s[gray].size())Merge(res, split(s[gray][0]));
            if (s[black].size())t = newnode(P), G[t] = s[black], res.push_back(t);
            del(x); return res;
        }
    }
    void work(int x)
    {
        if (col[x] != gray)return;
        if (tp[x] == Q)
        {
            int l = 0x3f3f3f3f, r = -0x3f3f3f3f;
            for (int i = 0;i < G[x].size();i++)
                if (col[G[x][i]] != co::white)l = min(l, i), r = max(r, i);
            for (int i = l + 1;i < r;i++)if (col[G[x][i]] != co::black)Fail();
            vector<int> son; if (l == r && col[G[x][l]] == gray)return work(G[x][l]);
            for (int i = 0, rev = 0;i < G[x].size();i++)
            {
                if (col[G[x][i]] != white)rev++;
                if (col[G[x][i]] != gray) { son.push_back(G[x][i]);continue; }
                if (rev == 1)Merge(son, split(G[x][i]));
                else Merge(son, Rev(split(G[x][i])));
            }
            swap(G[x], son);
        }
        else //白色点可以任排 黑色点也可以任排 灰色点排在黑色点两侧,但相对顺序不变
        {
            vector<int> s[3];
            for (int v : G[x])s[col[v]].push_back(v);
            if (s[gray].size() > 2)Fail();
            if (s[gray].size() == 1 && s[black].empty())return work(s[gray][0]);
            G[x].clear();
            int b = newnode(Q), t;G[x] = s[white];G[x].push_back(b);
            if (s[gray].size() >= 1)Merge(G[b], split(s[gray][0]));
            if (s[black].size())t = newnode(P), G[t] = s[black], G[b].push_back(t);
            if (s[gray].size() >= 2)Merge(G[b], Rev(split(s[gray][1])));
        }
    }
    void add(string _s) { s = _s; dfscol(n + 1); work(n + 1); remove(n + 1); }
    void print(int x)
    {
        if (1 <= x && x <= n)return cout << x << ' ', void();
        if (tp[x] == P)cout << '(';else cout << '[';
        for (int v : G[x])print(v);
        if (tp[x] == P)cout << ')';else cout << ']';
    }
    void Sol(int x, vector<int>& ans) { if (1 <= x && x <= n)ans.push_back(x);else for (int v : G[x])Sol(v, ans); }
    vector<int> Get() { vector<int> ans;Sol(n + 1, ans);return ans; }
};
const int N = 5500;
string s[N];
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);cout.tie(nullptr);
    PQT t; int n;
    cin >> n; t.build(n);
    for (int i = 1;i <= n;i++)
        cin >> s[i], t.add(s[i]);
    cout << "YES" << '\n';
    auto ans = t.Get();
    for (int i = 1;i <= n;i++)
    {
        for (int v : ans)cout << s[i][v - 1];
        cout << '\n';
    }
    return 0;
}
posted @ 2025-04-23 08:01  LUHCUH  阅读(17)  评论(0)    收藏  举报