Problem:
List

For a dynamic list $L$ of integers, perform a sequence of the following operations. $L$ has a special element called END at the end of the list and an element of $L$ is indicated by a cursor.

insert($x$): Insert $x$ before the element indicated by the cursor. After this operation, the cursor points the inserted element.

move($d$): Move the cursor to the end by $d$, if $d$ is positive. Move the cursor to the front by $d$, if $d$ is negative.

erase(): Delete the element indicated by the cursor. After this operation, the cursor points the element next to the deleted element. In case there is no such element, the cursor should point END.

In the initial state, $L$ is empty and the cursor points END.

Input

The input is given in the following format.

$q$
$query_1$
$query_2$
:
$query_q$

Each query $query_i$ is given by

0 $x$

or

1 $d$

or

2

where the first digits 0, 1 and 2 represent insert, move and erase operations respectively.

Output

Print all elements of the list in order after performing given operations. Print an element in a line.

Constraints

$1 \leq q \leq 500,000$

The cursor indicates an element of $L$ or END during the operations

Erase operation will not given when the cursor points END

$-1,000,000,000 \leq x \leq 1,000,000,000$

Moving distance of the cursor ($\sum{|d|}$) does not exceed 1,000,000

$L$ is not empty after performing all operations

Sample Input 1

5
0 1
0 2
0 3
1 1
2

Sample Output 1

3
1

Solution in C (judge verdict: Accepted)

#include <stdio.h>
#include <stdlib.h>
#define NUM_MAX 1000000001

typedef struct node_t
{
    int iNum;               // リストが持つ値
    struct node_t *pstPrev; // 前のノード
    struct node_t *pstNext; // 次のノード
} NODE;

// プロトタイプ宣言
NODE *stCreateNode(int iNum);
void vdInsert(int iArg, NODE **pstCursor);
void vdMove(int iArg, NODE **pstCursor);
void vdErase(NODE **pstCursor);
void vdPrint(NODE **pstCursor);

// 整数を保持するリストに対し、以下の操作を行う
// ・カーソルがさす要素の直前に整数Xを挿入
// ・整数Dの分だけカーソルを移動
// ・カーソルがさす要素を削除
int main()
{
    NODE *pstCursor; // カーソル
    int iNumOfQuery; // 命令数
    int iQuery;      // 命令
    int iArg;        // 引数
    int iCount;      // counter
    int iCount2;     // counter2

    // 初期化
    pstCursor = stCreateNode(NUM_MAX);
    // In: 命令数
    scanf("%d", &iNumOfQuery);

    for (iCount = 0; iCount < iNumOfQuery; iCount++)
    {
        // In: 命令
        scanf("%d", &iQuery);
        switch (iQuery)
        {
        case 0:
            // In: 引数
            scanf("%d", &iArg);
            vdInsert(iArg, &pstCursor);
            break;
        case 1:
            // In: 引数
            scanf("%d", &iArg);
            vdMove(iArg, &pstCursor);
            break;
        case 2:
            vdErase(&pstCursor);
            break;
        default:
            break;
        }
    }

    vdPrint(&pstCursor);

    // カーソル本体を解放
    free(pstCursor);

    return 0;
}

// ノードを作成する関数
NODE *stCreateNode(int iNum)
{
    // ノードの変数を動的確保
    NODE *pstNode = (NODE *)malloc(sizeof(NODE));
    // 確保できなければ強制終了
    if (pstNode == NULL)
    {
        exit(1);
    }
    // 初期化
    pstNode->iNum = iNum;
    pstNode->pstPrev = pstNode->pstNext = NULL;

    return pstNode;
}

// カーソルがさす前の要素に整数を挿入する関数
void vdInsert(int iArg, NODE **pstCursor)
{
    NODE *pstPe = (*pstCursor)->pstPrev;   // カーソルがさす1つ前のノードを退避
    NODE *pstNewNode = stCreateNode(iArg); // ノードを作成
    pstNewNode->pstPrev = pstPe;           // 新しいノードの1つ前のノードをカーソルと同じにする
    pstNewNode->pstNext = *pstCursor;      // 新しいノードの次のノードをカーソルにする
    // ひとつ前のノードが存在するならひとつ前のノードの次のノードを新しいノードに指定
    if (pstPe != NULL)
    {
        pstPe->pstNext = pstNewNode;
    }
    (*pstCursor)->pstPrev = pstNewNode; // カーソルを新しいノードのひとつ前に移動
    *pstCursor = pstNewNode;            // カーソルを新たなノードと共通化

    return;
}

// 引数分カーソルを移動させる関数
void vdMove(int iArg, NODE **pstCursor)
{
    int iCount;
    // カーソル移動が前と後ろで場合分け
    if (iArg > 0)
    {
        for (iCount = 0; iCount < iArg; iCount++)
        {
            *pstCursor = (*pstCursor)->pstNext; // カーソルを次に移動
        }
    }
    else if (iArg < 0)
    {
        for (iCount = 0; iCount > iArg; iCount--)
        {
            *pstCursor = (*pstCursor)->pstPrev; // カーソルを前に移動
        }
    }
    else
    {
        // 何もしない
    }

    return;
}

// カーソルがさす要素を削除する関数
void vdErase(NODE **pstCursor)
{
    NODE *pstPe = (*pstCursor)->pstPrev; // カーソルの前のノードを退避
    NODE *pstNe = (*pstCursor)->pstNext; // カーソルの次のノードを退避
    // 前後にノードが存在するならカーソルが指すノードを飛ばす処理を行う
    if (pstPe != NULL)
    {
        pstPe->pstNext = pstNe;
    }
    if (pstNe != NULL)
    {
        pstNe->pstPrev = pstPe;
    }
    free(*pstCursor);   // カーソルがさすノードを解放
    *pstCursor = pstNe; // カーソルを次のノードに移動

    return;
}

// カーソルを用いてリストを出力する関数
void vdPrint(NODE **pstCursor)
{
    NODE *pstNe;

    // カーソルを先頭に移動
    while ((*pstCursor)->pstPrev != NULL)
    {
        *pstCursor = (*pstCursor)->pstPrev;
    }
    // カーソルを動かしながら最後まで出力
    // ノードを一つずつ解放
    while (*pstCursor != NULL && (*pstCursor)->iNum != NUM_MAX)
    {
        pstNe = (*pstCursor)->pstNext;
        printf("%d\n", (*pstCursor)->iNum);
        free(*pstCursor);
        *pstCursor = pstNe;
    }

    return;
}