#include <cstdio>
#include <cstring>
#include <cctype>
#include <algorithm>
#include <vector>
#include <set>
#include <map>
#include <utility>

typedef long long LL;
#define rep(i,a,b) for(int i=a,_ds##i=b;i<=_ds##i;++i)
#define per(i,a,b) for(int i=a,_ds##i=b;i>=_ds##i;--i)
template<typename T> T rd(){T r;char c,n=0;while(!isdigit(c=getchar()))n=c=='-';r=c-'0';while(isdigit(c=getchar()))r=r*10+c-'0';return n?-r:r;}
#define rdi rd<int>
#define rdl rd<LL>

const int N = 305, M = 2e6 + 5, K = 605;
int T;
int n, m, k, th;
int a[M];

int pCnt = 0;
int pAt[K], pAvail[K];
bool pUp[K], pMod[K];
int pVal[K][5], pLen[K];

struct Operation {
    int typ, s1, s2;
    inline void Put() {
        if (typ == 2) printf("2 %d %d\n", s1, s2);
        else printf("1 %d\n", s1);
    }
} ops[M * 2];
int oCnt = 0;


inline int op1(int s) { ops[++oCnt] = {1, s}; return oCnt;}
inline int op2(int s1, int s2) { ops[++oCnt] = {2, s1, s2}; return oCnt; }
void UpdateR(int p) {
    if (pLen[p] == 2) {
        int q = pAt[pVal[p][2]];
        if (q && pUp[pVal[p][2]]) {
            op2(q, p);
            pAt[pVal[p][2]] = pUp[pVal[p][2]] = 0;
            pVal[q][pLen[q]--] = 0;
            pVal[p][pLen[p]--] = 0;
            UpdateR(q);
        }
    }
    if (pLen[p] == 1)
        pAvail[++pCnt] = p;
    else {
        pUp[pVal[p][pLen[p]]] = 1;
        pAt[pVal[p][pLen[p]]] = p;
        pAt[pVal[p][1]] = p;
    }
}
void RemoveUp(int p) {
    pAt[pVal[p][pLen[p]]] = 0;
    pUp[pVal[p][pLen[p]]] = 0;
    pVal[p][pLen[p]--] = 0;
    pMod[p] = 1;
    UpdateR(p);
}
void RemoveBot(int p) {
    pAt[pVal[p][1]] = 0;
    rep(i, 1, pLen[p] - 1)
        pVal[p][i] = pVal[p][i + 1];
    --pLen[p];
    UpdateR(p);
}
void AllocPool(int x) {
    int p = pAvail[pCnt];
    pUp[pVal[p][pLen[p]]] = 0;
    pUp[x] = 1;
    pVal[p][++pLen[p]] = x;
    pAt[x] = p;
    if (pLen[p] >= 2) --pCnt;
    pMod[p] = 1;
    op1(p);
}

int main() {
    freopen("meow.in", "r", stdin);
    freopen("meow.out", "w", stdout);
    T = rdi();
    while (T--) {
        n = rdi(), m = rdi(), k = rdi();
        th = n * 2 - 2;
        rep(i, 1, m) a[i] = rdi();
        pCnt = n - 1;
        rep(i, 1, n - 1) pAvail[i] = i;
        memset(pUp, 0, sizeof pUp);
        memset(pAt, 0, sizeof pAt);
        memset(pVal, 0, sizeof pVal);
        memset(pLen, 0, sizeof pLen);
        rep(i, 1, m) {
            printf("pAt[%d] = %d\n", a[i], pAt[a[i]]);
            if (pAt[a[i]]) {
                if (pUp[a[i]]) op1(pAt[a[i]]), RemoveUp(pAt[a[i]]);
                else op1(n), op2(pAt[a[i]], n), RemoveBot(pAt[a[i]]);
            } else if (pCnt > 0) {
                AllocPool(a[i]);
            } else {
                // Suspend i until a pool is available
                int idOp = op1(0);
                int x = a[i];
                memset(pMod, 0, sizeof(pMod));
                do {
                    ++i;
                    if (a[i] == x) break;
                    if (pAt[a[i]]) {
                        if (pUp[a[i]]) op1(pAt[a[i]]), RemoveUp(pAt[a[i]]);
                        else op1(n), op2(pAt[a[i]], n), pMod[n] = 1, RemoveBot(pAt[a[i]]);
                    } else if (pCnt > 0) {
                        AllocPool(a[i]);
                    }
                } while (i < m);
                int q = n;
                rep(mm, 1, n - 1) if (!pMod[mm]) {
                    q = mm; break;
                }
                ops[idOp].s1 = q;
                op1(q);
                ++i;
            }
        }
        printf("%d\n", oCnt);
        rep(i, 1, oCnt) {
            ops[i].Put();
        }
    }
    return 0;
}
