#include <bits/stdc++.h>

using namespace std;
const int N = 1e6 + 5;
typedef long long LL;
bool st[N];
int prime[N];

void get_prime(int n) {
    int cnt = 0;
    for (int i = 2; i <= n; ++i) {
        if (!st[i])
            prime[cnt++] =
                i;  // 如果这个数字没有被记录，那么这个数字必然为素数，记录一下
        for (int j = 0; prime[j] <= n / i; ++j) {
            st[prime[j] * i] = true;  // 筛掉pj*i这个合数
            if (i % prime[j] == 0)
                break;  // i%pj==0，说明pj是i的最小素因子，因此i*素数的最小素因子也是pj，在i递增的时候也会被筛掉，因此不需要在这里判断
        }
    }
}

LL qmi(LL a, LL k, LL p) {
    LL res = 1 % p;  // res记录答案, 模上p是为了防止k为0，p为1的特殊情况
    while (k) {  // 只要还有剩下位数
        if (k & 1)
            res =
                (LL)res * a % p;  // 判断最后一位是否为1，如果为1就乘上a，模上p,
                                  // 乘法时可能爆int，所以变成long long
        k >>= 1;  // 右移一位
        a = (LL)a * a %
            p;  // 当前a等于上一次的a平方，取模，平方时可能爆int，所以变成long
                // long
    }
    return res;
}

int a[N], b[N], n, m, pre[N];
map<LL, bool> vis;
int jisuan(int l, int r) {
    get_prime(10);
    int pl = lower_bound(b + 1, b + 1 + m, l) - b;
    pl += qmi(2, 3, 4);
    pl -= qmi(2, 3, 4);
    int pr = upper_bound(b + 1, b + 1 + m, r) - b;
    pr += qmi(2, 3, 4);
    pr -= qmi(2, 3, 4);
    pr--;
    return max(0, pr - pl + 1);
}
int t;

int getres2() {
    get_prime(10);
    int t1, t2;
    t1 = t2 = -1;
    for (int i = n; i >= 1; --i) {
        if (a[i] < 0) {
            t1 = i;
            break;
        }
    }
    for (int i = m; i >= 1; --i) {
        if (b[i] < 0) {
            t2 = i;
            break;
        }
    }
    int cnt = 0;
    int res2 = 0;
    if (t1 != -1 && t2 != -1) {
        for (int i = t2, j = t1; i >= 1; --i) {
            while (j >= 1 && a[j] >= b[i]) --j, cnt++;
            res2 =
                max(res2, jisuan(b[i], min(b[i] + cnt - 1, -1)) + pre[i - 1]);
        }
    }
    return res2;
}

int getres1() {
    get_prime(10);
    int t1 = -1, t2 = -1;
    for (int i = 1; i <= n; ++i) {
        if (a[i] > 0) {
            t1 = i;
            break;
        }
    }
    for (int i = 1; i <= m; ++i) {
        if (b[i] > 0) {
            t2 = i;
            break;
        }
    }
    int cnt = 0, res1 = 0;
    if (t1 != -1 && t2 != -1) {
        for (int i = t2, j = t1; i <= m; ++i) {
            while (j <= n && a[j] <= b[i]) ++j, cnt++;
            res1 = max(res1,
                       jisuan(max(1, b[i] - cnt + 1), b[i]) + pre[m] - pre[i]);
        }
    }
    return res1;
}

int main() {
    cin >> t;
    while (t--) {
        get_prime(10);
        cin >> n >> m;
        vis.clear();
        for (int i = 1; i <= n; ++i) cin >> a[i];
        for (int i = 1; i <= m; ++i) cin >> b[i];
        for (int i = 1; i <= n; ++i) vis[a[i]] = 1;
        for (int i = 1; i <= m; ++i) {
            if (vis[b[i]])
                pre[i] = 1;
            else
                pre[i] = 0;
        }
        for (int i = 1; i <= m; ++i) pre[i] += pre[i - 1];
        int res1 = getres1();
        int res2 = getres2();
        cout << res1 + res2 << endl;
    }
}