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 C# (judge verdict: Accepted)

using LIB;
using System;
using System.IO;
using System.Linq;
using System.Text;
using System.Collections.Generic;

class Program
{
    public static IO IO = new IO();
    static void Main(string[] args)
    {
        int n = IO.INT();
        LINKEDLIST<string> l = new LINKEDLIST<string>();
        for (int i = 0; i < n; i++)
        {
            string[] b = IO.STRING().Split(' ');
            switch (b[0])
            {
                case "insert":
                    l.ADDFIRST(b[1]);
                    break;
                case "delete":
                    l.DELETE(b[1]);
                    break;
                case "deleteFirst":
                    l.DELETEFIRST();
                    break;
                case "deleteLast":
                    l.DELETELAST();
                    break;
            }
        }
        IO.WRITE(string.Join(" ", l.TOARRAY()));
        IO.FLUSH();
    }
}

// ??£????????????
#region LINKEDLIST
namespace LIB
{
    public class LINKEDLIST<T> where T : IComparable
    {
        private class NODE { public T v; public NODE p, n; }
        private int c;
        private NODE n;
        public LINKEDLIST() { n = new NODE(); CLEAR(); }
        public void CLEAR() { n.n = n; n.p = n; c = 0; }
        public bool CONTAINS(T v) { return (SEARCH(v) != null); }
        public int COUNT() { return c; }
        public void ADDLAST(T v) { NODE a = new NODE(); a.v = v; ADDBEFORE(n, a); }
        public void ADDFIRST(T v) { NODE a = new NODE(); a.v = v; ADDAFTER(n, a); }
        public void ADDBEFORE(T t, T v) { NODE a = new NODE(); a.v = v; ADDBEFORE(SEARCH(t), a); }
        public void ADDAFTER(T t, T v) { NODE a = new NODE(); a.v = v; ADDAFTER(SEARCH(t), a); }
        public void DELETE(T v) { DELETE(SEARCH(v)); }
        public void DELETEFIRST() { DELETE(n.n); }
        public void DELETELAST() { DELETE(n.p); }
        public T FIRST() { return n.n.v; }
        public T LAST() { return n.p.v; }
        public T[] TOARRAY() { T[] r = new T[c]; NODE b = n.n; for (int i = 0; i < c; i++) { r[i] = b.v; b = b.n; } return r; }
        private NODE SEARCH(T v) { NODE r = null; NODE b = n.n; while (b != n) { if (b.v.CompareTo(v) == 0) { r = b; break; } b = b.n; } return r; }
        private void DELETE(NODE t) { if (t != n && t != null) { t.n.p = t.p; t.p.n = t.n; c--; } }
        private void ADDBEFORE(NODE m, NODE t) { NODE b = m.p; t.p = b; t.n = m; m.p = t; b.n = t; c++; }
        private void ADDAFTER(NODE m, NODE t) { NODE b = m.n; t.p = m; t.n = b; m.n = t; b.p = t; c++; }
    }
}
#endregion
namespace LIB
{
    public class IO
    {
        private const int WMAX = 1000;
        private StringBuilder S = new StringBuilder();
        private T R<T>(Func<string, T> f) { return f(Console.ReadLine()); }
        private T[] R<T>(Func<string, T> f, char c) { return STRING().Split(c).Select(f).ToArray(); }
        private T[] R<T>(Func<string, T> f, int l) { T[] r = new T[l]; for (int i = 0; i < l; i++) { r[i] = R(f); } return r; }
        private T[][] R<T>(Func<string, T> f, int l, char c) { T[][] r = new T[l][]; for (int i = 0; i < l; i++) { r[i] = R<T>(f, c); } return r; }
        private void W<T>(Func<T, string> f, T v, bool lf = true) { S.Append(f(v)); if (lf == true) { S.Append('\n'); } if (S.Length >= WMAX) { FLUSH(); } }
        public string STRING() { return R(s => s); }
        public string[] STRING(char c) { return R(s => s, c); }
        public string[] STRING(int l) { return R(s => s, l); }
        public string[][] STRING(int l, char c) { return R(s => s, l, c); }
        public int INT() { return R(int.Parse); }
        public int[] INT(char c) { return R(int.Parse, c); }
        public int[] INT(int l) { return R(int.Parse, l); }
        public int[][] INT(int l, char c) { return R(int.Parse, l, c); }
        public long LONG() { return R(long.Parse); }
        public long[] LONG(char c) { return R(long.Parse, c); }
        public long[] LONG(int l) { return R(long.Parse, l); }
        public long[][] LONG(int l, char c) { return R(long.Parse, l, c); }
        public double DOUBLE() { return R(double.Parse); }
        public double[] DOUBLE(char c) { return R(double.Parse, c); }
        public double[] DOUBLE(int l) { return R(double.Parse, l); }
        public double[][] DOUBLE(int l, char c) { return R(double.Parse, l, c); }
        public void WRITE(string s, bool lf = true) { W(v => v, s, lf); }
        public void WRITE(int s, bool lf = true) { W(v => v.ToString(), s, lf); }
        public void WRITE(long s, bool lf = true) { W(v => v.ToString(), s, lf); }
        public void WRITE(double s, bool lf = true) { W(v => v.ToString(), s, lf); }
        public void FLUSH() { Console.Write(S); S.Length = 0; }
    }
}