PQ 树



参考实现
#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;
}