洛谷链接:https://www.luogu.com.cn/problem/P1160
考察点:线性表的组织、插入删除与查找
一个学校里老师要将班上N个同学排成一列,同学被编号为1∼N,他采取如下的方法:
在所有同学按照上述方法队列排列完毕后,老师想知道从左到右所有同学的编号。
第1行为一个正整数N,表示了有N个同学。
第2−N行,第i行包含两个整数k,p,其中k为小于i的正整数,p为0或者1。若p为0,则表示将i号同学插入到k号同学的左边,p为1则表示插入到右边。
第N+1行为一个正整数M,表示去掉的同学数目。
接下来M行,每行一个正整数x,表示将x号同学从队列中移去,如果x号同学已经不在队列中则忽略这一条指令。
1行,包含最多N个空格隔开的正整数,表示了队列从左到右所有同学的编号,行末换行且无空格。
输入
4 1 0 2 1 1 0 2 3 3
输出
2 4 1
将同学2插入至同学1左边,此时队列为:21
将同学3插入至同学2右边,此时队列为:231
将同学4插入至同学1左边,此时队列为:2341
将同学3从队列中移出,此时队列为:241
同学3已经不在队列中,忽略最后一条指令
最终队列:241
对于20%的数据,有N≤10;对于40%的数据,有N≤1000;对于100%的数据,有N,M≤100000。
本题考查点为线性表。由于我们需要对题目进行按照要求采用双向链表进行操作即可。但是如果单纯的用链表会产生TLE等情况。这时想到数组具有查找快的特点,链表具有插入删除快的特点。同时注意到学生的顺序是依次连续增加的。所以可以将二者的优点结合起来,用结构体数组存链表。这样就解决了TLE的问题。
#include <stdio.h> #include <stdlib.h> struct Node { int flag; int id; struct Node *left; struct Node *right; }queue[100010]; int main() { struct Node *head; head = &queue[0]; head->id = 1; head->flag = 0; head->left = NULL; head->right = NULL; int i; int n; scanf("%d", &n); for (i = 2; i <= n; i++) { int k, p; struct Node *next = NULL; next = &queue[i - 1]; scanf("%d%d", &k, &p); struct Node *temp = &queue[k - 1]; if (p == 0) { next->id = i; next->flag = 0; next->right = temp; if (temp->left != NULL) { next->left = temp->left; temp->left->right = next; } else { head = next; } temp->left = next; } else { next->id = i; next->flag = 0; next->left = temp; if (temp->right != NULL) { next->right = temp->right; temp->right->left = next; } temp->right = next; } } int m; scanf("%d", &m); for (i = 0; i < m; i++) { int temp; scanf("%d", &temp); queue[temp - 1].flag = 1; } struct Node *temp = head; while (temp != NULL) { if (temp->flag != 1) { printf("%d ", temp->id); } temp = temp->right; } return 0; }