#include <stdio.h>
#include <stdlib.h>
#include <limits.h>

typedef struct {
    long long value;   // element value
    int stream;        // which stream it belongs to
    int index;         // position inside the stream
    long long ready;   // earliest time this stream can be used again (kept for tie-break consistency)
} Node;

typedef struct {
    Node *arr;
    int size;
    int capacity;
} MinHeap;

/* Compare two nodes:
   - primary: value
   - secondary: ready time
   - tertiary: stream id
   - quaternary: index
   returns <0 if a < b, 0 if equal, >0 if a > b
*/
static int cmpNodes(const Node *a, const Node *b) {
    if (a->value < b->value) return -1;
    if (a->value > b->value) return 1;
    if (a->ready < b->ready) return -1;
    if (a->ready > b->ready) return 1;
    if (a->stream < b->stream) return -1;
    if (a->stream > b->stream) return 1;
    if (a->index < b->index) return -1;
    if (a->index > b->index) return 1;
    return 0;
}

void swap(Node *a, Node *b) {
    Node tmp = *a;
    *a = *b;
    *b = tmp;
}

MinHeap* createHeap(int capacity) {
    if (capacity <= 0) capacity = 16;
    MinHeap heap = (MinHeap)malloc(sizeof(MinHeap));
    if (!heap) { perror("malloc heap"); exit(1); }
    heap->arr = (Node*)malloc(capacity * sizeof(Node));
    if (!heap->arr) { perror("malloc heap->arr"); exit(1); }
    heap->size = 0;
    heap->capacity = capacity;
    return heap;
}

void heapify(MinHeap *heap, int i) {
    int smallest = i;
    int left = 2*i + 1;
    int right = 2*i + 2;

    if (left < heap->size && cmpNodes(&heap->arr[left], &heap->arr[smallest]) < 0)
        smallest = left;
    if (right < heap->size && cmpNodes(&heap->arr[right], &heap->arr[smallest]) < 0)
        smallest = right;

    if (smallest != i) {
        swap(&heap->arr[i], &heap->arr[smallest]);
        heapify(heap, smallest);
    }
}

Node extractMin(MinHeap *heap) {
    if (heap->size <= 0) {
        fprintf(stderr, "extractMin called on empty heap\n");
        exit(1);
    }
    Node root = heap->arr[0];
    heap->arr[0] = heap->arr[heap->size - 1];
    heap->size--;
    if (heap->size > 0) heapify(heap, 0);
    return root;
}

void insertHeap(MinHeap *heap, Node item) {
    if (heap->size == heap->capacity) {
        int newcap = heap->capacity * 2;
        Node tmp = (Node)realloc(heap->arr, newcap * sizeof(Node));
        if (!tmp) { perror("realloc heap->arr"); exit(1); }
        heap->arr = tmp;
        heap->capacity = newcap;
    }

    int i = heap->size++;
    heap->arr[i] = item;
    while (i != 0 && cmpNodes(&heap->arr[(i-1)/2], &heap->arr[i]) > 0) {
        swap(&heap->arr[i], &heap->arr[(i-1)/2]);
        i = (i-1)/2;
    }
}

int main(void) {
    int K, D;
    if (scanf("%d %d", &K, &D) != 2) {
        fprintf(stderr, "Expected: K D\n");
        return 0;
    }
    if (K <= 0) {
        // nothing to do
        return 0;
    }

    int sizes = (int)malloc(K * sizeof(int));
    if (!sizes) { perror("malloc sizes"); return 1; }

    long long *streams = (long long)malloc(K * sizeof(long long));
    if (!streams) { perror("malloc streams"); return 1; }

    for (int i = 0; i < K; ++i) {
        if (scanf("%d", &sizes[i]) != 1) {
            fprintf(stderr, "Failed to read size for stream %d\n", i);
            return 1;
        }
        if (sizes[i] < 0) {
            fprintf(stderr, "Invalid stream size %d for stream %d\n", sizes[i], i);
            return 1;
        }
        if (sizes[i] == 0) {
            streams[i] = NULL;
            continue;
        }
        streams[i] = (long long*)malloc(sizes[i] * sizeof(long long));
        if (!streams[i]) { perror("malloc stream elements"); return 1; }
        for (int j = 0; j < sizes[i]; ++j) {
            if (scanf("%lld", &streams[i][j]) != 1) {
                fprintf(stderr, "Failed to read element %d of stream %d\n", j, i);
                return 1;
            }
            if (streams[i][j] < 0) {
                printf("Invalid input\n");
                return 0;
            }
        }
    }

    MinHeap *heap = createHeap((K > 16) ? K * 2 : 16);
    long long ready = (long long)calloc(K, sizeof(long long));
    if (!ready) { perror("calloc ready"); return 1; }

    // Initialize heap with first element of each stream
    for (int i = 0; i < K; ++i) {
        if (sizes[i] > 0) {
            Node node = { streams[i][0], i, 0, 0 };
            insertHeap(heap, node);
        }
    }

    long long currentTime = 0;
    int first = 1;
    while (heap->size > 0) {
        Node minNode = extractMin(heap);

        // Ensure stream is ready (fast-forward time if necessary)
        if (currentTime < ready[minNode.stream]) currentTime = ready[minNode.stream];

        if (!first) printf(" ");
        printf("%lld", minNode.value);
        first = 0;

        currentTime++;

        // Update ready time for this stream
        ready[minNode.stream] = currentTime + D;

        // Push next element from this stream if available
        if (minNode.index + 1 < sizes[minNode.stream]) {
            Node next = { streams[minNode.stream][minNode.index + 1],
                          minNode.stream,
                          minNode.index + 1,
                          ready[minNode.stream] };
            insertHeap(heap, next);
        }
    }

    printf("\n");

    // cleanup
    for (int i = 0; i < K; ++i) free(streams[i]);
    free(streams);
    free(sizes);
    free(ready);
    free(heap->arr);
    free(heap);

    return 0;
}