题意:给定一个最多能保存M个数的栈。按1,2,3,...,N和pop随机。你应该判断一个给定的数字序列是否是堆栈中可能的弹出序列。例如,如果M是5,N是7,我们可以从堆栈中获得1,2,3,4,5,6,7,但不能获得3,2,1,7,5,6,4。 输入规格: 每个输入文件包含一个测试用例。对于每种情况,第一行包含3个数字(都不超过1000): M(堆栈的最大容量)、push序列的长度)和K(要检查的pop序列的数量)。接着是K行,每一行包含N个数字的弹出序列。一行中的所有数字都用空格隔开。 输出规格: 对于每个pop序列,如果它确实是堆栈中可能的pop序列,则打印一行“YES ”,否则打印“NO”。
分析:连续的pop出来的是降序数列,如果后一个数比前一个数大,那这两个数之间一定有push,按照连续降序给数列分段,比如5643721分段为0/5/643/721(在最前面加了一个0,这样在后面方便比较),在每一个子段里面数据一定是降序的,否则输出NO,每一个子段的第一个数是按升序排列的,否则输出NO,比如3217564,分段后0/321/75/64,其每一个子段第一个数排列出来是0,3,7,6,不是升序的。
同时还要注意栈的最大数量,在一个push操作和pop操作之间时,栈有最大数量,在读入到升序数据时,计算a[i]-i+1的值(i-1是目前已pop数量,a[i]是push过的数量)并与栈的最大数量比较。
#include<bits/stdc++.h>
using namespace std;
int a[1005];
int main(){
int m,n,k;
cin>>m>>n>>k;
a[0] = 0;
while(k--){
bool f = true;
for(int i = 1;i<=n;i++){
cin>>a[i];
}
queue<int>q;
q.push(0);
int maxx = 0; //记录上一个子段的开头
for(int i = 1;i<=n;i++){
if(a[i]>a[i-1]){
if(maxx>a[i]||a[i]-i+1>m){ //不可能的方案
f = false;
break;
}
q.push(i);
maxx = a[i];
}
}
if(f){
cout<<"YES";
}else cout<<"NO";
if(k)cout<<endl;
}
return 0;
}