Luo Gu 1155: dual-stack Sort
Description meaning of the questions:
- Given a length \ (n-\) sequence \ ((n-\ Leq 1000) \) , two initially empty stack, and asked whether the sequence of operation of four rows by ascending order.
- \ (1: \) if the sequence is not empty, the first element onto the stack \ (S_1 \) . Operation referred to as \ (A \) .
- \ (2: \) If the stack \ (S_1 \) is not empty, the \ (S_1 \) the top element to eject the output sequence. Operation referred to as \ (D \) .
- \ (3: \) input sequence is not empty, the first element onto the stack \ (S_2 \) . Operation referred to as \ (C \) .
- \ (4: \) If the stack \ (S_2 \) is not empty, the \ (S_2 \) the top element to eject the output sequence. Operation referred to as \ (D \) .
Output Description:
- Output operation sequence lexicographically smallest, if not the nature of the sort dual stack, output \ (0 \) .
Ideas:
- Write for a long stack monotone greedy + + analog is to be reminded of a bipartite graph.
- I write a solution to a problem commemorate the passing of three hours.
- First, there is such a character.
- If this condition exists \ (i <j <k \ ) and \ (A (K) <A (I) <A (J) \) , then the \ (a (i), a (j) \) can not be in within the same stack, which is a necessary and sufficient condition.
- prove:
- Necessity: If \ (i <j <k \ ) and \ (A (K) <A (I) <A (J) \) , then since \ (a (i) \) and \ (a (j ) \) behind there is a smaller number \ (a (K) \) , so \ (a (i), a (j) \) not be popped from the stack. So from the bottom of the stack to the top of the stack of elements is not a monotonically decreasing descending order, then there will pop up when the reverse order, so the \ (a (i), a (j) \) can not be assigned to the same stack.
- Sufficiency: If \ (a (i), a (j) \) condition is not satisfied, then the conflict will not occur during operation.
- All particles larger than \ (a (j) \) elements in the stack are constant;
- All less than \ (a (j) \) elements, for example, \ (A (I) <A (J) \) , due to the absence of the back \ (A (K) <A (I) \) , so \ (a (i) \) have been popped.
- Therefore, the \ (a (j) \) pushed onto the stack, the stack from the bottom to the top of the stack may be kept still descending, the entire process is carried out smoothly.
- With the above nature, we only need to meet all the conditions of points into two stacks, this step can be transformed into graph theory problem.
- Enumerate all points, if \ (i, j \) satisfy the conditions capable of a stack, then \ (i, j \) plus side.
- Of course enumerate all the points of taking into account the above conditions, a very bad things will happen.
- I point to the need to enumerate \ (O (n ^ 2) \) time complexity, and I find there is no need to scan backwards smaller number is required (O (n) \) \ time complexity, total it will be \ (O (the n-^ 3) \) , can not pass.
- To find ways to optimize this step, we can pretreatment \ (f (i) = min (a_j) \) . \ (J \) from \ (I \) to the \ (n-\) .
- This can be \ (O (n ^ 2) \) enumeration point, determines whether \ (i, j \) satisfy the condition, that is, \ (. 1 + F_ {J} <a_i <a_j \) .
- Then determines whether a bipartite graph, to determine whether to meet the nature of the dual-stack sort, can be staining.
- And because the lexicographically smallest requirement, so the priority is assigned to the point \ (S_1 \) in.
- After sorting analog dual-stack, answer.
Complexity analysis:
- FIG built enumerate all points \ (O (^ n-2) \) .
- Staining determined bipartite graph \ (O (n-m +) \) .
- Analog sorting stack \ (O (n-) \) .
- The total time complexity is \ (O (^ n-2) \) , can pass.
Code:
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e3 + 10;
const int INF = 0x3f3f3f3f;
int n, a[maxn], f[maxn];
int head[maxn], ver[maxn<<5], nex[maxn<<5], tot;
inline void add_edge(int x, int y){
ver[++tot] = y; nex[tot] = head[x]; head[x] = tot;
}
int color[maxn];
bool dfs(int x, int c)
{
color[x] = c;
for(int i = head[x]; i; i = nex[i])
{
int y = ver[i];
if(!color[y])
{
if(!dfs(y, 3 - c)) return false;
}
else if(color[y] == c) return false;
}
return true;
}
int main()
{
scanf("%d", &n); f[n+1] = INF;
for(int i = 1; i <= n; i++) scanf("%d", &a[i]);
for(int i = n; i >= 1; i--) f[i] = min(f[i+1], a[i]);
for(int i = 1; i < n; i++)
for(int j = i + 1; j < n; j++)
if(a[i] > f[j+1] && a[i] < a[j])
add_edge(i, j), add_edge(j, i);
bool flag = true;
for(int i = 1; i <= n; i++)
{
if(!color[i])
{
if(!dfs(i, 1))
{
flag = false;
break;
}
}
}
if(flag == false) puts("0");
else
{
stack<int> stk1, stk2;
int cnt = 1;
for(int i = 1; i <= n; i++)
{
if(color[i] == 1)
{
stk1.push(a[i]);
printf("a ");
}
else{
stk2.push(a[i]);
printf("c ");
}
while((!stk1.empty() && stk1.top() == cnt) || (!stk2.empty() && stk2.top() == cnt))
{
if(!stk1.empty() && stk1.top() == cnt)
{
stk1.pop();
cnt++;
printf("b ");
}
else
{
stk2.pop();
cnt++;
printf("d ");
}
}
}
}
return 0;
}