P1155 [NOIP2008 提高组] 双栈排序(二分图)
Posted Harris-H
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P1155 [NOIP2008 提高组] 双栈排序(二分图)相关的知识,希望对你有一定的参考价值。
P1155 [NOIP2008 提高组] 双栈排序(二分图)
大佬的题解,大概看懂了。
因为 i < j , a [ i ] > a [ j ] i<j,a[i]>a[j] i<j,a[i]>a[j],所以必须用一个栈暂存 a [ i ] a[i] a[i],不然 a [ i ] a[i] a[i]比 a [ j ] a[j] a[j]先进栈,但是要求 a [ i ] a[i] a[i]比 a [ j ] a[j] a[j]先出栈,所以不能满足。
然后三个的话,首先 i < k , a [ i ] > a [ k ] i<k,a[i]>a[k] i<k,a[i]>a[k]与上面同理,所以要用一个栈来保存 a [ i ] a[i] a[i],又因为 a [ j ] > a [ k ] a[j]>a[k] a[j]>a[k],所以要用一个栈来保存 a [ j ] a[j] a[j]。如果 a [ i ] , a [ j ] a[i],a[j] a[i],a[j]在同一个栈的话, a [ i ] a[i] a[i]要比 a [ k ] a[k] a[k]后出栈, a [ j ] a[j] a[j]要比 a [ k ] a[k] a[k]后出栈, a [ i ] a[i] a[i]要比 a [ j ] a[j] a[j]先出栈。
也就是说 a [ i ] , a [ j ] a[i],a[j] a[i],a[j]要存起来,如果存到一个栈里, a [ i ] a[i] a[i]比 a [ j ] a[j] a[j]先进栈,但是后出栈则不行。
有点类似逆序对,但又不完全是。
code
// Problem: P1155 [NOIP2008 提高组] 双栈排序
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P1155
// Memory Limit: 128 MB
// Time Limit: 1000 ms
// Date: 2021-07-04 21:23:48
// --------by Herio--------
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int N=1e3+5,M=2e4+5,inf=0x3f3f3f3f,mod=1e9+7;
#define mst(a,b) memset(a,b,sizeof a)
#define PII pair<int,int>
#define fi first
#define se second
#define pb emplace_back
#define SZ(a) (int)a.size()
#define ios ios::sync_with_stdio(false),cin.tie(0)
void Print(int *a,int n){
for(int i=1;i<n;i++)
printf("%d ",a[i]);
printf("%d\\n",a[n]);
}
int n,p[N],mn[N],cnt=1;
stack<int>s[2];
void out(char ch){
putchar(ch);putchar(' ');
}
bool Pop(int i){
if(!s[i].empty()&&s[i].top()==cnt){
out(i?'d':'b');s[i].pop();++cnt;
return true;
}
return false;
}
void Push(int x,int i){
if(i==1) while(Pop(0));//如果要push 尽可能把之前第一个栈中可以的出来,保证字典序最小.
while(!s[i].empty()&&s[i].top()<x) //直到不能保持栈的单调性才出栈.
if(!Pop(i)) Pop(i^1); //如果此时不能出栈则一定是另一个出栈.
if(i==1) while(Pop(0)); //可能又有新的可以丢.
s[i].push(x);out(i?'c':'a');
}
vector<int>g[N];
int c[N];
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",&p[i]);mn[n+1]=n+1;
for(int i=n;i;i--) mn[i]=min(mn[i+1],p[i]);
for(int i=1;i<=n;i++)
for(int j=i+1;j<=n;j++)
if(p[i]<p[j]&&mn[j+1]<p[i]) g[i].pb(j),g[j].pb(i),c[i]=c[j]=-1;
queue<int>q;
for(int i=1;i<=n;i++)
if(!~c[i]){ //二分图染色 判断是否有解
q.push(i);
c[i]=0;
while(!q.empty()){
int u=q.front();q.pop();
for(int v:g[u]){
if(~c[v]&&c[u]==c[v]) return puts("0"),0;
if(!~c[v]) q.push(v);
c[v]=c[u]^1;
}
}
}
for(int i=1;i<=n;i++) Push(p[i],c[i]);
bool flag = true;
while (flag) {
flag = false;
while(Pop(0)) flag = true;
while(Pop(1)) flag = true;
}
return 0;
}
以上是关于P1155 [NOIP2008 提高组] 双栈排序(二分图)的主要内容,如果未能解决你的问题,请参考以下文章
Vijos1605 NOIP2008 提高组T4 双栈排序 BFS