题意:
这是一个一维推箱子的游戏,你站在0这个位置,然后在这个轴上有n个箱子。
保证没有箱子在0这个位置,然后有 m 个特殊的位置,你每次推箱子都是推动一个单位,如果你把箱子推向的下一个单位上有箱子,那么那个箱子也会往后挪动一个单位。
问:经过你的努力,你最多可以让多少个箱子在特殊位置上。
思路:首先小结论是正半轴和负半轴的第一个箱子一定要在特殊位置上这样不会更劣,所以对于两个半轴分开讨论,枚举第一个箱子在哪个特殊位置上。预处理后缀本来就在特殊位置上的箱子数,然后因为往后枚举时第一个不动的箱子也是单调的所以用双指针解决。
/*keep on going and never give up*/
#include<cstdio>
#include<iostream>
#include<queue>
#include<algorithm>
#include<map>
using namespace std;
typedef pair<int, int> pii;
#define int long long
#define lowbit(x) x&(-x)
#define endl '\n'
#define wk is zqx ta die
int a[200005];
int b[200005];
vector<int> a1;
vector<int> a2;
vector<int> b1;
vector<int> b2;
int pre[200005];
map<int, int> mp;
signed main() {
std::ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int t;
cin >> t;
while (t--) {
a1.clear();
a2.clear();
b1.clear();
b2.clear();
int n, m;
cin >> n >> m;
mp.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++) {
if (a[i] > 0) {
a1.push_back(a[i]);
} else {
a2.push_back(-a[i]);
}
}
for (int i = 1; i <= m; i++) {
if (b[i] > 0) {
b1.push_back(b[i]);
mp[b[i]] = 1;
} else {
b2.push_back(-b[i]);
}
}
int ans = 0;
int r = 0;
if (a1.size() != 0 && b1.size() != 0) {
pre[0] = mp[a1[0]];
for (int i = 1; i < a1.size(); i++) {
pre[i] = pre[i - 1] + mp[a1[i]];
}
for (int i = 0; i < b1.size(); i++) {
if (a1[0] > b1[i]) {
continue;
}
while (r + 1 < a1.size() && a1[r + 1] <= b1[i] + r + 1) {
r++;
}
int tp = upper_bound(b1.begin(), b1.end(), b1[i] + r) - b1.begin();
tp = tp - i;
ans = max(ans, tp + pre[a1.size() - 1] - pre[r]);
}
}
int sum = ans;
// cout << ans << endl;
ans = 0;
r = 0;
mp.clear();
if (a2.size() != 0 && b2.size() != 0) {
sort(b2.begin(), b2.end());
sort(a2.begin(), a2.end());
for (int i = 0; i < b2.size(); i++) {
mp[b2[i]] = 1;
}
pre[0] = mp[a2[0]];
for (int i = 1; i < a2.size(); i++) {
pre[i] = pre[i - 1] + mp[a2[i]];
}
for (int i = 0; i < b2.size(); i++) {
if (a2[0] > b2[i]) {
continue;
}
while (r + 1 < a2.size() && a2[r + 1] <= b2[i] + r + 1) {
r++;
}
int tp = upper_bound(b2.begin(), b2.end(), b2[i] + r) - b2.begin();
tp = tp - i;
ans = max(ans, tp + pre[a2.size() - 1] - pre[r]);
}
}
sum += ans;
cout << sum << endl;
}
return 0;
}