Consider a special queue which is a linear structure that allows insertions at one end, yet deletions at both ends. Your job is to check, for a given insertion sequence, if a deletion sequence is possible. For example, if we insert 1, 2, 3, 4, and 5 in order, then it is possible to obtain 1, 3, 2, 5, and 4 as an output, but impossible to obtain 5, 1, 3, 2, and 4.
Input Specification:
Each input file contains one test case. For each case, the first line gives 2 positive integers N and K (≤10), which are the number of insertions and the number of queries, respectively. Then N distinct numbers are given in the next line, as the insertion sequence. Finally K lines follow, each contains N inserted numbers as the deletion sequence to be checked.
All the numbers in a line are separated by spaces.
Output Specification:
For each deletion sequence, print in a line yes
if it is indeed possible to be obtained, or no
otherwise.
Sample Input:
5 4
10 2 3 4 5
10 3 2 5 4
5 10 3 2 4
2 3 10 4 5
3 5 10 4 2
Sample Output:
yes
no
yes
yes
中文翻译:
考虑一个特殊的队列,它是一个线性结构,允许一端插入,两端都有删除。您的工作是检查给定的插入序列是否可以删除序列。例如,如果我们按顺序插入1、2、3、4和5,则可以获得1、3、2、5和4作为输出,但不可能获得5、1、3、2和4。
输入规格:
每个输入文件包含一个测试用例。对于每种情况,第一行给出2个正整数N和K(≤10) ,分别是插入数和查询数。然后在下一行中给出N个不同的数字,作为插入序列。最后是K行,每行包含N个插入的数字作为要检查的删除序列。
一行中的所有数字都用空格分隔。
输出规格:
对于每个删除序列,如果确实可以获得,则在行中打印“是”,否则打印“否”。
样本输入:
首先我们先去理解题意,比方说1234为默认序列,然后他给了个4123这个序列,那么就是按照4123的顺序删除其中的数据,4之前必须有123,3之前必须有12........,然后插入只能是一端,先是4,那么我们从一端插入1234,之后两端删除,先是4,从右面删除,然后是1,从左面删除,然后是2,从左面删除,然后是3从右面删除。同时如果一个数被删除之后,那么在后面的序列我们就不需要考虑这个数了,比方说2删除了,那么3之前的就只要有1即可。
从上面的一个例子我们是先判断一个数,他之前是要先出现哪些数的,我们现需要构造一个顺序函数,即某个数字出现之前,要出现那些数字,同时,我们还需要一个数组来标记一个数字是否已经被删除,还要判断两端的是否为对应的数(即我们要删除的数),如果不是那么就是NO。根据这一个我们写出了如下的代码:
#include <stdio.h>
int main(){
int i,j;
int k,n,front,flag,m,t,rear;
scanf("%d%d",&n,&k);
int a[n],c[n],b[n],book[n],g,h,l;//c[n]是存储当前的未删除的数字,a[n]就是顺序数组,b[n]就是我们要删除数字的顺序。
for(i=0;i<n;i++){
scanf("%d",&a[i]);
book[i]=1;//所有数据都还未被删除
c[i]=-1;//防止随机数据和我们要删除的数据重复
}
for(i=0;i<k;i++){
front=0;
flag=0;
l=0;
rear=-1;//添加一个数据是从0下标开始的,所以我们让rear是-1
for(j=0;j<n;j++)book[j]=1;
for(j=0;j<n;j++){
h=0;
scanf("%d",&b[j]);//输入要加入的数据
for(g=0;g<n;g++)if(a[g]==b[j])break;//找到该数据在a数组中的位置,方便下面先存入他前面的数据
if(l<=g){for(m=0,l=0;l<=g;l++){//如果要存入的数据大于前面已经有的数据,我们就需要更新数组。
if(book[l]==0)continue;//如果已经被删除就不执行
c[h++]=a[l];
front=0;//因为数组是往0上面插入的,所以我们就让头重新变成0.
}
rear=h-1;
}
if(c[front]==b[j]){//看头部是否为要删除的数据
book[g]=0;
front++;//删除头部,由于再内存中并没有删除,所以我们需要在逻辑上让front++,来达到逻辑上的删除。
}
else if(c[rear]==b[j]){//看尾部是否为要删除的数据
book[g]=0;
rear--;
}
else {j++;//都不是就是no
flag=1;
break;
}
}
for(t=j;t<n;t++)scanf("%d",&b[t]);//由于break,导致一些数据未被scanf,所以在这里再用一个循环接受该数据。
if(flag)printf("no\n");
else printf("yes\n");
}
}
我写出来的代码只是逻辑上删除了数据,但是在内存上并没有将数据删除干净。