题意
五维偏序,在线。
题解
上 bitset。分别考虑每一维,把在这一维不大于询问的所有编号对应的 bit 设为 1。全部与起来,1 的个数就是答案。
暴力 bitset 空间复杂度不行,分块优化一下即可。即块之间做前缀和,块内暴力 set。
注意分块对象是 n n n,不是值域。
#include <bits/stdc++.h>
using namespace std;
int read(){
int f = 1, x = 0;
char c = getchar();
while (c < '0' || c > '9'){if(c == '-') f = -f; c = getchar();}
while (c >= '0' && c <= '9')x = x * 10 + c - '0', c = getchar();
return f * x;
}
int n, m, a[50005][5], b[5];
pair<int, int> p[5][50005];
bitset<50000> bs[5][225], ans, tmp;
int B, BB;
void init(){
n = read(), m = read();
for (B = 1; B * B <= n; ++B)
;
--B;
BB = n / B;
for (int i = 0; i < n; ++i)
for (int j = 0; j < 5; ++j)
a[i][j] = read();
for (int j = 0; j < 5; ++j){
for (int i = 0; i < n; ++i)
p[j][i].first = a[i][j], p[j][i].second = i;
sort(p[j], p[j] + n);
bs[j][0].reset();
for (int i = 1; i <= B; ++i){
bs[j][i] = bs[j][i - 1];
for (int t = (i - 1) * BB; t < i * BB; ++t)
bs[j][i].set(p[j][t].second);
}
}
}
bool get(int i, int x){
int l = 0, r = n;
auto pp = p[i];
while (r > l){
int mid = (l + r) >> 1;
if (pp[mid].first > x) r = mid;
else l = mid + 1;
}
if (l == 0) {
tmp.reset();
return false;
}
tmp = bs[i][l / BB];
int cur = (l / BB) * BB;
while (cur < l){
tmp.set(pp[cur].second);
++cur;
}
return true;
}
void solve(){
int lstans = 0, q = read();
while (q--){
for (int i = 0; i < 5; ++i)
b[i] = read() ^ lstans;
ans.set();
for (int i = 0; i < 5; ++i){
if (get(i, b[i])) ans &= tmp;
else {
ans.reset();
break;
}
}
lstans = (int)ans.count();
printf("%d\n", lstans);
}
}
int main(){
int T = read();
while (T--){
init();
solve();
}
return 0;
}