[洛谷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;
}
posted @ 2019-06-21 23:08  kma_093  阅读(168)  评论(0编辑  收藏  举报