洛谷P1155 【NOIP2008】雙棧排序
阿新 • • 發佈:2018-11-04
題目連結
題解
這題有點神啊。。
我們仔細觀察一下,發現兩個棧內元素必須為降序
那麼有結論 如果有\(i < j < k\) 且 \(a[k] < a[i] < a[j]\)則\(i\)和\(j\)不能存在於同一個棧
證明:
因為棧內元素必須降序,
那麼加入\(a[j]\)時一定彈出了\(a[i]\),而又因為從小到大排序,
所以\(a[k]\)應該在\(a[i]\)前彈出,故結論正確。
證畢!
因為是兩個棧
那麼我們可以搞一個二分圖染色
最後貪心模擬一遍
Code
#include<bits/stdc++.h> using namespace std; const int N = 1010; int a[N], s1[N], s2[N], Min[N], t1, t2, ans[N<<1], len, n; bool G[N][N], vis[N]; int z[N]; void dfs(int x, int c) { vis[x] = 1; z[x] = c; for (int i = 1; i <= n; i++) { if (!G[x][i]) continue; if (!vis[i]) dfs(i, c^1); else if (c == z[i]) { printf("0\n"); exit(0); } } return ; } int main() { scanf("%d", &n); for (int i = 1; i <= n; i++) scanf("%d", &a[i]); Min[n+1] = 2147483647; for (int i = n; i >= 1; i--) Min[i] = min(Min[i+1], a[i]); for (int i = 1; i < n; i++) for (int j = i+1; j <= n; j++) if (Min[j+1] < a[i] && a[i] < a[j]) G[i][j] = G[j][i] = 1; for (int i = 1; i <= n; i++) if (!vis[i]) dfs(i, 0); int now = 1; for (int i = 1; i <= n; i++) { if (!z[i]) { while (s1[t1] == now) { now++; t1--; ans[++len] = 1; } s1[++t1] = a[i]; len++; } else { while (s1[t1] == now) { now++; t1--; ans[++len] = 1; } while (s2[t2] == now) { now++; t2--; ans[++len] = 3; } s2[++t2] = a[i]; ans[++len] = 2; } } while (now <= n) { if (s1[t1] == now) ans[++len] = 1, t1--; else ans[++len] = 3, t2--; now++; } for (int i = 1; i <= len; i++) printf("%c ", ans[i]+'a'); return 0; }