队列安排
题目描述
一个学校里老师要将班上N个同学排成一列,同学被编号为1~N,他采取如下的方法:-
先将 1 1 1号同学安排进队列,这时队列中只有他一个人;
-
2 − N 2-N 2−N号同学依次入列,编号为i的同学入列方式为:老师指定编号为i的同学站在编号为 1 ∼ ( i − 1 ) 1\sim (i -1) 1∼(i−1)中某位同学(即之前已经入列的同学)的左边或右边;
-
从队列中去掉 M ( M < N ) M(M<N) M(M<N)个同学,其他同学位置顺序不变。
在所有同学按照上述方法队列排列完毕后,老师想知道从左到右所有同学的编号。
输入输出格式
输入格式
第 1 1 1行为一个正整数 N N N,表示了有 N N N个同学。
第 2 − N 2-N 2−N行,第 i i i行包含两个整数 k , p k,p k,p,其中 k k k为小于 i i i的正整数, p p p为 0 0 0或者 1 1 1。若 p p p为 0 0 0,则表示将 i i i号同学插入到 k k k号同学的左边, p p p为 1 1 1则表示插入到右边。
第 N + 1 N+1 N+1行为一个正整数 M M M,表示去掉的同学数目。
接下来 M M M行,每行一个正整数 x x x,表示将 x x x号同学从队列中移去,如果 x x x号同学已经不在队列中则忽略这一条指令。
输出格式
第 1 1 1行,包含最多 N N N个空格隔开的正整数,表示了队列从左到右所有同学的编号,行末换行且无空格。
输入输出样例
输入样例
4
1 0
2 1
1 0
2
3
3
输出样例 #1
2 4 1
说明
将同学 2 2 2插入至同学 1 1 1左边,此时队列为:
21 2 1 21
将同学 3 3 3插入至同学 2 2 2右边,此时队列为:
231 2 3 1 231
将同学 4 4 4插入至同学 1 1 1左边,此时队列为:
2341 2 3 4 1 2341
将同学 3 3 3从队列中移出,此时队列为:
241 2 4 1 241
同学 3 3 3已经不在队列中,忽略最后一条指令
最终队列:
241 2 4 1 241
数据范围
对于 20 % 20\% 20%的数据,有 N ≤ 10 N≤10 N≤10;
对于 40 % 40\% 40%的数据,有 N ≤ 1000 N≤1000 N≤1000;
对于 100 % 100\% 100%的数据,有 N , M ≤ 100000 N, M≤100000 N,M≤100000。
开始用的单向列表,发现双向也可以。但这都会超时。
复杂度可能为O(n*n),找到数据n,操作可以忽略,共n次。
时间浪费在了查找上面。
那我们开个数组,把每个编号同学对号入座,保存他的左右编号。
需要的时候,直接把他拉过来即可。
附上tle代码
#include<iostream>
#include<cstdio>
#include<malloc.h>
using namespace std;
struct node {
int key;
struct node* next;
};
int read()
{
int flag=1,ans=0;
char am=getchar();
while((am>'9'||am<'0')&&am!='-') am=getchar();
if(am=='-') flag=-1,am=getchar();
while(am>='0'&&am<='9') ans=ans*10+am-'0',am=getchar();
return ans*flag;
}
void add(int i,int p1,int k,node *head) {
// 0 左, 1右
node *am=head;
node *tep=head->next;
while(tep)
{
if(tep->key==p1) {
node *p=(node*)malloc(sizeof(struct node));
p->key=i;
if(k==0) {
p->next=tep;
am->next=p;
} else {
p->next=tep->next;
tep->next=p;
}
return;
}
am=tep;
tep=tep->next;
}
}
void del(int p1,node *head)
{
node *tep=head->next;
node *am=head;
while(tep)
{
if(tep->key==p1)
{
am->next=tep->next;
return;
}
am=tep;
tep=tep->next;
}
}
node* build() {
node *head=(node*)malloc(sizeof(struct node));
head->key=-1;
node *tep=(node*)malloc(sizeof(struct node));
head->next=tep;
tep->key=1;
tep->next=NULL;
return head;
}
void print(node *head) {
node *te=head->next;
while(te) {
printf("%d ",te->key);
te=te->next;
}
}
int main(void) {
int n,p,k;
node *head=build();
n=read();
for(int i=2; i<=n; i++) {
p=read();
k=read();
add(i,p,k,head);
}
int m;
m=read();
for(int i=1;i<=m;i++)
{
int num;
num=read();
del(num,head);
}
print(head);
}
pe[0]相当于头结点,不然你去哪里找第一人。
第一次用数组模拟链表,感觉有点新鲜呀。
#include<iostream>
#include<cstdio>
#include<malloc.h>
using namespace std;
struct node {
int key;
int next,pre;
};
node pe[100003];
int read()
{
int flag=1,ans=0;
char am=getchar();
while((am>'9'||am<'0')&&am!='-') am=getchar();
if(am=='-') flag=-1,am=getchar();
while(am>='0'&&am<='9') ans=ans*10+am-'0',am=getchar();
return ans*flag;
}
void add(int i,int p1,int k) {
//k 0 左,1 右
pe[i].key=i;
if(k==0)
{
pe[i].next=pe[p1].key;
pe[i].pre=pe[p1].pre;
pe[pe[p1].pre].next=pe[i].key;
pe[p1].pre=pe[i].key;
}
else
{
pe[i].next=pe[p1].next;
pe[i].pre=pe[p1].key;
pe[pe[p1].next].pre=pe[i].key;
pe[p1].next=pe[i].key;
}
}
void del(int p1)
{
if(pe[p1].key==-1) return;
pe[pe[p1].pre].next=pe[p1].next;
pe[pe[p1].next].pre=pe[p1].pre;
pe[p1].key=-1;
}
node build() {
pe[0].next=pe[1].key;
pe[1].next=-1;
pe[1].pre=0;
pe[0].pre=-1;
pe[1].key=1;
}
void print() {
int tep=pe[0].next;
while(1)
{
if(pe[tep].key)
{
if(pe[tep].key!=-1)//说明此人被踢出了
{
printf("%d ",tep);
}
}
else break;
tep=pe[tep].next;
}
}
int main(void) {
int n,p,k;
n=read();
build();
for(int i=2; i<=n; i++) {
p=read();
k=read();
add(i,p,k);
}
int m;
m=read();
for(int i=1;i<=m;i++)
{
int num;
num=read();
del(num);
}
print();
}