Problem:
Doubly Linked List

Your task is to implement a double linked list.

Write a program which performs the following operations:

insert x: insert an element with key x into the front of the list.

delete x: delete the first element which has the key of x from the list. If there is not such element, you need not do anything.

deleteFirst: delete the first element from the list.

deleteLast: delete the last element from the list.

Input

The input is given in the following format:

n

command1

command2

...

commandn

In the first line, the number of operations n is given. In the following n lines, the above mentioned operations are given in the following format:

insert x

delete x

deleteFirst

deleteLast

Output

Print all the element (key) in the list after the given operations. Two consequtive keys should be separated by a single space.

Constraints

The number of operations ≤ 2,000,000

The number of delete operations ≤ 20

0 ≤ value of a key ≤ 109

The number of elements in the list does not exceed 106

For a delete, deleteFirst or deleteLast operation, there is at least one element in the list.

Sample Input 1

7
insert 5
insert 2
insert 3
insert 1
delete 3
insert 6
delete 5

Sample Output 1

6 1 2

Sample Input 2

9
insert 5
insert 2
insert 3
insert 1
delete 3
insert 6
delete 5
deleteFirst
deleteLast

Sample Output 2

1

Solution in JAVA (judge verdict: Time Limit Exceeded)

import java.util.Scanner;
import java.util.ArrayList;
import java.lang.Integer;
import java.lang.StringBuilder;
import java.lang.Math;



enum CmdOp {
  INSERT("insert"),
  DELETE("delete"),
  DELETE_FIRST("deleteFirst"),
  DELETE_LAST("deleteLast"),
  UNDEFINED("UNDEFINED");

  private String name;

  private CmdOp(String str) {
    this.name = str;
  }

  private String getName() {
    return name;
  };

  @Override
  public String toString() {
    return getName();
  }

  public static CmdOp cmdStrToCmdOp(String cmd) {
    CmdOp ret;
    switch(cmd) {
      case "insert":
        ret = CmdOp.INSERT;
        break;
      case "delete":
        ret = CmdOp.DELETE;
        break;
      case "deleteFirst":
        ret = CmdOp.DELETE_FIRST;
        break;
      case "deleteLast":
        ret = CmdOp.DELETE_LAST;
        break;
      default:
        ret = CmdOp.UNDEFINED;
        break;
    }

    return ret;
  }

}

class Cmd {
  private final CmdOp cmd;
  private final int target;

  public Cmd(String cmd, int target) {
    this.cmd = CmdOp.cmdStrToCmdOp(cmd);
    this.target = target;
  }


  public int getTarget() {
    return target;
  }

  public CmdOp getCmdOp() {
    return cmd;
  }

  @Override
  public String toString() {
    return "cmd: " + cmd.toString() +  ", target: " + getTarget();
  }

}
class Node {
  public Node next;
  public Node prev;
  public int value;

  public Node(int value) {
    this.value = value;
  }
}

class LinkedList {
  private Node head;
  private Node tail;
  // sentinel
  private final Node NIL;

  public LinkedList() {
    NIL = new Node(Integer.MAX_VALUE);
    NIL.next = NIL;
    NIL.prev = NIL;
    head = NIL;
    tail = NIL;
  }

  public void insert(int x) {
    Node n = new Node(x);
    n.next = head;
    n.prev = head.prev;
    head.prev = n;

    if (head == NIL) {
      tail = n;
      NIL.prev = tail;
    }

    // update head
    head = n;
    NIL.next = head;
  }

  public boolean delete(int x) {
    Node cursor = head;
    while (cursor != NIL) {
      if (cursor.value == x) {
        if (cursor == head) {
          return deleteFirst();
        }
        if (cursor == tail) {
          return deleteLast();
        }
        cursor.prev.next = cursor.next;
        cursor.next.prev = cursor.prev;
        return true;
      }
      cursor = cursor.next;
    }
    return false;
  }

  public boolean deleteFirst() {
    if (head == NIL) {
      return false;
    }
    if (head == tail) {
      tail = NIL;
      tail.prev = NIL;
      tail.next = NIL;
    }

    head = head.next;
    head.prev = NIL;
    return true;
  }

  public boolean deleteLast() {
    if (tail == NIL) {
      return false;
    }

    if (head == tail) {
      head = NIL;
      head.prev = NIL;
      head.next = NIL;
    }

    tail.prev.next = NIL;
    tail = tail.prev;

    return true;
  }

  public void print() {
    StringBuilder buf = new StringBuilder();
    Node cursor = head;
    while (cursor != NIL) {
      buf.append(cursor.value);
      buf.append(" ");
      cursor = cursor.next;
    }
    System.out.println(buf.toString().trim());
  }
}


public class Main {
  private static int N;
  private static ArrayList<Cmd> cmds;
  private static LinkedList head;

  private static void run() {
    head = new LinkedList();
    for (Cmd cmd: cmds) {
      switch(cmd.getCmdOp()) {
      case INSERT:
        head.insert(cmd.getTarget());
        break;
      case DELETE:
        head.delete(cmd.getTarget());
        break;
      case DELETE_FIRST:
        head.deleteFirst();
        break;
      case DELETE_LAST:
        head.deleteLast();
        break;
      default:
        System.out.println("error");
        break;
      }
    }
    head.print();
  }

  public static void main(String[] args) {
    Scanner in = new Scanner(System.in);
    N = in.nextInt();

    cmds = new ArrayList<Cmd>(N);
    for (int i = 0; i < N; i++) {
      String cmdstr = in.next();
      if (cmdstr.equals("deleteFirst") || cmdstr.equals("deleteLast")) {
        cmds.add(new Cmd(cmdstr, 0));
      } else {
        cmds.add(new Cmd(cmdstr, in.nextInt()));
      }
    }

    //for (Cmd cmd: cmds) {
    //  System.out.println(cmd);
    //}

    // init
    run();
  }
}