Problem Description
给一个初始的入栈序列,其次序即为元素的入栈次序,栈顶元素可以随时出栈,每个元素只能入栈依次。输入一个入栈序列,后面依次输入多个序列,请判断这些序列是否为所给入栈序列合法的出栈序列。
例如序列1,2,3,4,5是某栈的压入顺序,序列4,5,3,2,1是该压栈序列对应的一个出栈序列,但4,3,5,1,2就不可能是该序列的出栈序列。假设压入栈的所有数字均不相等。
Input
第一行输入整数n(1<=n<=10000),表示序列的长度。
第二行输入n个整数,表示栈的压入顺序。
第三行输入整数t(1<=t<=10)。
后面依次输入t行,每行n个整数,表示要判断的每一个出栈序列。
Output
对应每个测试案例输出一行,如果由初始入栈序列可以得到该出栈序列,则输出yes,否则输出no。
Sample Input
5
1 2 3 4 5
2
4 5 3 2 1
4 3 5 1 2
Sample Output
yes
no
既然要模拟出栈顺序,那么在入栈顺序数组和出栈顺序数组之间肯定有一个栈来模拟这个过程,但是在压入栈中的过程中栈顶元素可以在这个时候出栈,这也就意味着不能在全部压栈之后再判断出栈,而是一边压栈一边判断。
怎么判断呢?按顺序访问时,当入栈顺序序列的某个元素等于出栈顺序的某个元素时,这个元素肯定是要出栈的,所以我们直接忽略它不使之入栈,也就达成了让他出栈的效果。除去这种情况以外,那就肯定要压栈,因为还没到这个元素该出栈的时候。而且在这种顺序访问的时候只有一个元素出栈以后才能访问下一个出栈序列的元素,因为这是一个过程模拟,前一个元素没有出栈后一个元素肯定不能出栈。
当入栈过程结束后,所需的就是把栈中元素按照剩余的(入栈时未访问的)出栈顺序弹出,看最后栈是否成功清空。
那么就有如下思路:
- 输入入栈序列,出栈序列,构建模拟栈
- 按照上述,直接对过程进行模拟
- 入栈结束后对于栈中元素进行按序弹出
判断:
#include<pch.h>
#include <iostream>
#include <cstdio>
#include <bits/stdc++.h>
#include <map>
#include <algorithm>
#include <stack>
#include <iomanip>
#include <cstring>
#include <cmath>
#define DETERMINATION main
#define lldin(a) scanf_s("%lld", &a)
#define println(a) printf("%lld\n", a)
#define reset(a, b) memset(a, b, sizeof(a))
const int INF = 0x3f3f3f3f;
using namespace std;
const double PI = acos(-1);
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
const int mod = 1000000007;
const int tool_const = 19991126;
const int tool_const2 = 33;
inline ll lldcin()
{
ll tmp = 0, si = 1;
char c;
c = getchar();
while (c > '9' || c < '0')
{
if (c == '-')
si = -1;
c = getchar();
}
while (c >= '0' && c <= '9')
{
tmp = tmp * 10 + c - '0';
c = getchar();
}
return si * tmp;
}
///Untersee Boot IXD2(1942)
/**Although there will be many obstructs ahead,
the desire for victory still fills you with determination..**/
/**Last Remote**/
ll tmpa[43432], tmpb[43442]//压入顺序与出栈顺序
int DETERMINATION()
{
ll n;
cin >> n;
for (int i = 1; i <= n; i++)
cin >> tmpa[i];
ll t;
cin >> t;
while (t--)
{
stack<ll>sta;//用栈来模拟
for (int j= 1; j <= n; j++)
cin >> tmpb[j];
ll pointer1 = 1, pointer2 = 1;//分别代表压入顺序数组的下标与出栈顺序数组的下标
while (pointer1 <= n)//把压入顺序中的元素全部压入栈中之前
{
if (tmpa[pointer1] == tmpb[pointer2])//当压入顺序的元素等于出栈顺序的元素:直接使其出栈(也就是不入栈,如同题目所言)
{
pointer1++, pointer2++;
}
else//否则就要把它压入栈中并访问下一个压入顺序数组中的元素,因为它按照出栈顺序来说还没有出栈
{
sta.push(tmpa[pointer1]);
pointer1++;
}
}
//压入过程结束后就可以直接按照其出栈顺序数组模拟即可,也就是说栈顶元素等于出栈元素[pointer2]的时候就使其出栈,否则留在栈中
while (!sta.empty()&&sta.top() == tmpb[pointer2++])
sta.pop();
if (sta.empty())//如果栈里边没有元素,那么代表这个出栈顺序是合法的
cout << "yes" << endl;
else//否则就不合法
cout << "no" << endl;
}
return 0;
}