[洛谷P1155] 双栈排序
题目链接:##
题目分析:##
先考虑单栈排序时有哪些元素不能在一个栈里,再将这些元素之间两两连边,跑二分图染色判断是否能有合法方案
输出使用模拟
我的算法是\(O(n^3)\)的,不知道为什么就过了(。。),想到优化了再回来补档
代码:##
#include<bits/stdc++.h>
#define INF (1000000000+7)
#define N (1000+5)
using namespace std;
inline int read() {
int cnt = 0, f = 1; char c;
c = getchar();
while (!isdigit(c)) {
if (c == '-') f = -f;
c = getchar();
}
while (isdigit(c)) {
cnt = (cnt << 3) + (cnt << 1) + c - '0';
c = getchar();
}
return cnt * f;
}
int n, tot, color[N], opr[N], cnt, sta[N], sta2[N], top1 = 0, top2 = 0;
bool check[N], flag;
int a[N];
int nxt[N * 2], first[N], to[N * 2];
void Add(int x, int y) {
nxt[++tot] = first[x];
first[x] = tot;
to[tot] = y;
}
bool Dfs(int u) {
for (register int i = first[u]; i; i = nxt[i]) {
int v = to[i];
if (color[v] == -1) {
color[v] = color[u] ^ 1;
if(!Dfs(v)) return false;
} else if(color[v] == color[u]) {
return false;
}
}
return true;
}
bool pd(int p) {
if (p == 0) return false;
for (register int i = 1; i < p; i++) if(!check[i]) return false;
return true;
}
void Reverse(int p) {
for (register int i = p; i <= n; i++) color[a[i]] ^= 1;
}
int main() {
// freopen("input.in","r",stdin);
n = read();
memset(check, 0, sizeof(check));
for (register int i = 1; i <= n; i++) color[i] = -1;
for (register int i = 1; i <= n; i++) a[i] = read();
a[0] = INF;check[0] = 1;
for (register int i = 1; i <= n; i++) {
// if(!pd(a[i])) {
// cout<<a[i]<<endl;
for (register int k = i; k >= 1; k--)
if (a[k] < a[i] && !pd(a[k])) {
Add(a[i], a[k]), Add(a[k], a[i]);
// cout<<a[i]<<" "<<a[k];
// cout<<endl;
}
// }
check[a[i]] = 1;
}
// cout<<"%%%"<<endl;
flag = 1;
for (register int i = 1; i <= n; i++) {
if (color[i] == -1) {
color[i] = 0;
if (!Dfs(i)) {
flag = 0;
break;
}
}
}
if (!flag) return printf("0\n"), 0;
else {
memset(check, 0, sizeof(check));
// for (register int j = 1; j <= n; j++) cout<<color[j]<<" "; cout<<endl;
for (register int i = 1; i <= n; i++) {
// if (!top1 && color[a[i]] == 1) Reverse(i);
// for (register int j = 1; j <= n; j++) cout<<color[j]<<" "; cout<<endl;
while (pd(sta[top1]) && top1) {
printf("b ");
check[sta[top1]] = 1;
top1--;
}
if (!top1 && color[a[i]] == 1) Reverse(i);
if (color[a[i]] == 0) {
sta[++top1] = a[i];
printf("a ");
// check[a[i]] = 1;
}
while (pd(sta2[top2]) && top2) {
printf("d ");
check[sta2[top2]] = 1;
top2--;
}
if (color[a[i]] == 1) {
sta2[++top2] = a[i];
printf("c ");
// check[a[i]] = 1;
}
// cout<<"i = " <<i<<" top1:"<<top1<<" top2:"<<top2<<endl;
}
while(top1 + top2) {
while (pd(sta[top1]) && top1) {
printf("b ");
check[sta[top1]] = 1;
top1--;
}
// for (register int i = 1; i <= n; i++) cout<<"check "<< check[i]<<endl;
while (pd(sta2[top2]) && top2) {
printf("d ");
check[sta2[top2]] = 1;
top2--;
}
}
}
return 0;
}