solution

$30$bitの上半分と下半分をそれぞれまとめて作る。 $A_1$を$1 = 2^0$や$2^{15}$にしてこれを$A_2$に$2^{15}$回足し、それぞれの時点で一致する他の$A_j$ ($j \ge 2$)に足し込む。 $A_1 = 1$の制約は必須。 クエリ数は$2 \cdot 2^{15} + 2N + \alpha$。 一般にはbit数$B$と分割数$K$で$O(K(2^{B/K} + N))$クエリ。

$N \le 2 \times 10^5$ にも関わらず $Q \le 5.5 \times 10^5$ であるので$1$要素あたり高々$2.5$回で構築しないといけない。 となると選択肢はbitsetとしての包含関係の順に上手くやるか、上で述べた解法のどちらか。

implementation

#include <bits/stdc++.h>
#define REP(i, n) for (int i = 0; (i) < (int)(n); ++ (i))
#define REP3(i, m, n) for (int i = (m); (i) < (int)(n); ++ (i))
#define ALL(x) begin(x), end(x)
using namespace std;

vector<pair<int, int> > solve(int n, const vector<int> & a) {
    // precondition
    constexpr int SIZE = 30;
    assert (a[0] == 1);
    assert (*max_element(ALL(a)) < (1 << SIZE));

    // prepare api
    vector<int> b(n, 0);
    vector<pair<int, int> > ops;
    auto op1 = [&](int x) {
        ops.emplace_back(x, -1);
        b[x] = 1;
    };
    auto op2 = [&](int y, int z) {
        ops.emplace_back(y, z);
        b[y] += b[z];
    };

    // categorize a_i's
    vector<vector<int> > lo(1 << (SIZE / 2));
    vector<vector<int> > hi(1 << (SIZE / 2));
    REP3 (x, 2, n) {
        constexpr int HALF = SIZE / 2;
        constexpr int HALF_MASK = (1 << HALF) - 1;
        lo[a[x] &  HALF_MASK].push_back(x);
        hi[a[x] >> HALF     ].push_back(x);
    }

    // construct lower half
    op1(0);
    op1(1);
    REP3 (s, 1, 1 << (SIZE / 2)) {
        assert (b[1] == s);
        for (int x : lo[s]) {
            op2(x, 1);
        }
        op2(1, 0);
    }

    // construct upper half
    REP (i, SIZE / 2) {
        op2(0, 0);
    }
    REP3 (s, 1, 1 << (SIZE / 2)) {
        assert (b[1] == (s << (SIZE / 2)));
        for (int x : hi[s]) {
            op2(x, 1);
        }
        op2(1, 0);
    }

    // construct a_0 and a_1
    op1(0);
    int i = 1 << SIZE;
    while (not (a[1] & i)) i >>= 1;
    op1(1);
    i >>= 1;
    for (; i; i >>= 1) {
        op2(1, 1);
        if (a[1] & i) op2(1, 0);
    }

    // postcondition
    assert (ops.size() <= 550000);
    assert (b == a);
    return ops;
}

int main() {
    // input
    int n; cin >> n;
    vector<int> a(n);
    REP (i, n) cin >> a[i];

    // solve
    vector<pair<int, int> > ops = solve(n, a);

    // output
    cout << ops.size() << endl;
    for (auto op : ops) {
        if (op.second == -1) {
            cout << 1 << " " << op.first + 1 << endl;
        } else {
            cout << 2 << " " << op.first + 1 << " " << op.second + 1 << endl;
        }
    }
    return 0;
}