#include <cstdio>
#include <vector>
#include <set>
#include <utility>

#if 0
#define dbg(...) fprintf(stderr, __VA_ARGS__),fflush(stderr)
#else
#define dbg(...)
#endif

using namespace std;

typedef pair <int,int> pii;

class RangeTree {
    int kk;
    vector <pii> tree;
public:
    RangeTree(int n, int inf) {
        kk = 1;
        while (kk < n) {
            kk *= 2;
        }
        tree.resize(kk * 2 + 10, pii(inf, -1));
        for (int i = 0; i < n; ++i) {
            tree[i + kk] = pii(inf, i);
        }
        for (int i = kk - 1; i >= 1; --i) {
            update(i);
        }
    }

    int getValue(int x) const {
        return tree[x + kk].first;
    }

    int getMinPos() const {
        return tree[1].second;
    }

    void change(int x, int val) {
        tree[x + kk] = pii(val, x);
        x += kk;
        while (x > 1) {
            x /= 2;
            update(x);
        }
    }

private:
    void update(int t) {
        if (tree[2 * t].first == tree[2 * t + 1].first) {
            tree[t] = tree[2 * t + 1];
        } else {
            tree[t] = min(tree[2 * t], tree[2 * t + 1]);
        }
    }
};

bool can(const vector <int> & cards, const vector <int> & next, int m, int k) {
    dbg("can for m = %d\n", m);
    int n = int(cards.size());
    RangeTree tree(m, n + 1);
    int taked, played, inHand;
    for (taked = 0, played = 0, inHand = 0; taked <= n && played < m; ) {
        if (tree.getValue(played) != n + 1) {
            dbg("play %d\n", played);
            tree.change(played, n + 1);
            inHand -= 1;
            ++played;
            continue;
        }
        if (taked == n) {
            break;
        }
        if (inHand == k) {
            int forDrop = tree.getMinPos();
            dbg("drop %d\n", forDrop);
            tree.change(forDrop, n + 1);
            inHand -= 1;
        }
        if (cards[taked] < m && tree.getValue(cards[taked]) != n + 1) {
            dbg("drop %d\n", cards[taked]);
            tree.change(cards[taked], n + 1);
            inHand -= 1;
        }
        dbg("take %d\n", cards[taked]);
        if (played <= cards[taked] && cards[taked] < m) {
            inHand += 1;
            tree.change(cards[taked], next[taked]);
        } else {
            dbg("drop %d\n", cards[taked]);
        }
        ++taked;
    }
    return played == m;
}

void solve() {
    int n, m, k;
    scanf("%d%d%d", &n, &m, &k);
    vector <int> cards(n);
    for (int i = 0; i < n; ++i) {
        scanf("%d", &cards[i]);
        --cards[i];
    }
    vector <int> next(n);
    vector <int> last(m, n);
    for (int i = n - 1; i >= 0; --i) {
        next[i] = last[cards[i]];
        last[cards[i]] = i;
        dbg("next[%d] = %d\n", i, next[i]);
    }

    int L = 0;
    int R = m + 1;
    while (L + 1 < R) {
        int M = (L + R) / 2;
        if (can(cards, next, M, k)) {
            L = M;
        } else {
            R = M;
        }
    }
    printf("%d\n", L);
}

int main() {
    freopen("game.in", "r", stdin);
    freopen("game.out", "w", stdout);

    int tt;
    scanf("%d", &tt);

    for (int ii = 0; ii < tt; ++ii) {
        dbg("Case #%d\n", ii);
        solve();
    }

    return 0;
}