P1160 队列安排
题目描述
一个学校里老师要将班上N个同学排成一列,同学被编号为1∼N,他采取如下的方法:
- 先将1号同学安排进队列,这时队列中只有他一个人;
- 2-N2−N号同学依次入列,编号为i的同学入列方式为:老师指定编号为i的同学站在编号为1∼(i−1)中某位同学(即之前已经入列的同学)的左边或右边;
- 从队列中去掉M(M<N)个同学,其他同学位置顺序不变。
在所有同学按照上述方法队列排列完毕后,老师想知道从左到右所有同学的编号。
输入格式
第1行为一个正整数N,表示了有N个同学。
第2-N行,第ii行包含两个整数k,p,其中k为小于ii的正整数,p为0或者1。若p为0,则表示将ii号同学插入到k号同学的左边,p为1则表示插入到右边。
第N+1行为一个正整数M,表示去掉的同学数目。
接下来M行,每行一个正整数x,表示将x号同学从队列中移去,如果xx号同学已经不在队列中则忽略这一条指令。
输出格式
1行,包含最多N个空格隔开的正整数,表示了队列从左到右所有同学的编号,行末换行且无空格。
题解
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class Main {
static BufferedReader scan = new BufferedReader(new InputStreamReader(System.in));
public static void main(String[] args) throws IOException {
int N = Integer.parseInt(scan.readLine());
int count[] = new int[N];
int [][]operation = new int[N+1][2];
String []s = new String[2];
for(int i=2;i<operation.length;i++) {
s= scan.readLine().split(" ");
operation[i][0] = Integer.parseInt(s[0]);
operation[i][1] = Integer.parseInt(s[1]);
}
int M = Integer.parseInt(scan.readLine());
int []numb = new int[M];
for(int i=0;i<numb.length;i++) {
numb[i] = Integer.parseInt(scan.readLine());
}
scan.close();
LNode list = new LNode();
LNode p= new LNode();
LNode first = new LNode(1);
list.next=first;
first.prime = list;
for(int i=2;i<operation.length;i++) {
p = list.next;
p.insert(p, i, operation[i][0], operation[i][1]);
}
for(int i=0;i<numb.length;i++) {
p = list.next;
p.delete(p,numb[i],count);
}
p = list.next;
while(p!=null) {
System.out.print(p.data+" ");
p=p.next;
}
}
}
class LNode {
public int data;
public LNode prime;
public LNode next;
public LNode(int data) {
this.data = data;
}
public LNode() {
}
void insert(LNode p,int i,int location,int direction) {
LNode l = new LNode(i);
while(p.data!=location) {
p=p.next;
}
if(direction== 0) { //向左插
l.next = p.prime.next;
l.prime = p.prime;
p.prime.next = l;
p.prime = l;
}else { //向右插
if(p.next==null) {
l.prime = p;
p.next = l;
}else {
l.prime = p;
l.next = p.next;
p.next.prime = l;
p.next = l;
}
}
}
void delete(LNode p,int data,int []count) {
if(count[data]==1) {
return;
}
while(p!=null) {
if(p.data==data) {
if(p.next==null) {
p.prime.next=null;
}else {
p.prime.next=p.next;
p.next.prime=p.prime;
}
count[data] = 1;
break;
}
p=p.next;
}
}
@Override
public String toString() {
return this.data+"";
}
}
注解
该题解后三个点为超时点目前还没有解决。仅提供解题思路。
2023.5.29修改(java已过100%)
一种基于LinkedList和HashMap的解决方案。在这个解决方案中,使用一个HashMap来存储值和相应节点的映射关系,使得查找操作时间复杂度为O(1)。而LinkedList用于存储数据并保持插入的顺序。
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Map;
class Node {
int value;
Node prev, next;
Node(int value) {
this.value = value;
}
}
public class Main {
static BufferedReader scan = new BufferedReader(new InputStreamReader(System.in));
public static void main(String[] args) throws IOException {
int N = Integer.parseInt(scan.readLine());
Map<Integer, Node> nodeLookup = new HashMap<>();
Node head = new Node(1);
nodeLookup.put(1, head);
//首先读取一个整数N,然后读取N行输入。每一行都包含一个整数X和一个标志B。
//它在列表中查找值为X的元素,然后在其之前(如果B为0)或者之后(如果B为1)插入新的元素。
//新元素的值为当前的循环次数(从2开始)。如果找不到值为X的元素,那么新元素将不会被插入。
for (int i = 2; i <= N; i++) {
String[] input = scan.readLine().split(" ");
int X = Integer.parseInt(input[0]);
int B = Integer.parseInt(input[1]);
Node newNode = new Node(i);
Node oldNode = nodeLookup.get(X);
if (B == 0) {
newNode.next = oldNode;
newNode.prev = oldNode.prev;
if (oldNode.prev != null) {
oldNode.prev.next = newNode;
}
oldNode.prev = newNode;
if (oldNode == head) {
head = newNode;
}
} else {
newNode.prev = oldNode;
newNode.next = oldNode.next;
if (oldNode.next != null) {
oldNode.next.prev = newNode;
}
oldNode.next = newNode;
}
nodeLookup.put(i, newNode);
}
//然后,读取一个整数M,然后读取M行输入。每一行包含一个整数,表示需要从列表中删除的元素。
int M = Integer.parseInt(scan.readLine());
for (int i = 0; i < M; i++) {
int data = Integer.parseInt(scan.readLine());
Node nodeToRemove = nodeLookup.get(data);
if (nodeToRemove != null) {
if (nodeToRemove.prev != null) {
nodeToRemove.prev.next = nodeToRemove.next;
}
if (nodeToRemove.next != null) {
nodeToRemove.next.prev = nodeToRemove.prev;
}
if (nodeToRemove == head) {
head = nodeToRemove.next;
}
nodeLookup.remove(data);
}
}
for (Node node = head; node != null; node = node.next) {
System.out.print(node.value + " ");
}
}
}