#include using namespace std; template struct MergeableSet{ int N, M; int nxt = 0; vector isBlock, seen; vector idx; vector> s; vector> bit; // N: number of sets, M: upper limit of sets MergeableSet(const int N, const int M) : N(N), M(M + 1), isBlock(N), seen(M + 1), idx(N), s(N){ } void toBlock(int id){ isBlock[id] = true; idx[id] = nxt++; vector emp((M + 63) / 64); bit.emplace_back(emp); for(auto x : s[id]){ bit[idx[id]][x / 64] |= 1ULL << (x % 64); } }; void insert(int id, int x){ assert(0 <= x && x < M); if(isBlock[id]){ bit[idx[id]][x / 64] |= 1ULL << (x % 64); } else{ bool isContained = false; for(auto y : s[id]){ if(x == y){ isContained = true; } } if(isContained){ return; } s[id].emplace_back(x); if((int) s[id].size() + 1 >= BLOCK){ toBlock(id); } } } void erase(int id, int x){ assert(0 <= x && x < M); if(isBlock[id]){ bit[idx[id]][x / 64] &= ~(1ULL << (x % 64)); } else{ vector tmp; for(auto y : s[id]){ if(x != y){ tmp.emplace_back(y); } } s[id] = tmp; } } void shift(int id, int x){ if(isBlock[id]){ int d = x / 64, m = x % 64; int siz = bit[idx[id]].size(); vector emp(siz); for(int i = (int) siz - 1; i >= 0; i--){ int j = i + d; unsigned long long tmp1 = bit[idx[id]][i], tmp2 = bit[idx[id]][i]; tmp1 <<= m; tmp2 >>= 64 - m; if(0 <= j && j < siz){ emp[j] |= tmp1; } if(0 <= j + 1 && j + 1 < siz){ emp[j + 1] |= tmp2; } } bit[idx[id]] = emp; } else{ vector tmp; for(auto y : s[id]){ if(0 <= y + x && y + x < M){ tmp.emplace_back(y + x); } } s[id] = tmp; } } bool equal(int id1, int id2){ if(isBlock[id2]) swap(id1, id2); if(isBlock[id1] && isBlock[id2]){ return (bit[idx[id1]] == bit[idx[id2]]); } else if(isBlock[id1] && !isBlock[id2]){ int idx1 = idx[id1]; vector tmp = bit[idx1]; for(auto x : s[id2]){ if(!(bit[idx1][x / 64] & (1ULL << (x % 64)))){ return false; } tmp[x / 64] &= ~(1ULL << (x % 64)); } for(int i = 0; i < (int) bit[idx1].size(); i++){ if(tmp[i] != 0ULL){ return false; } } return true; } return (s[id1] == s[id2]); } // return one of elements int intersect(int id1, int id2){ if(isBlock[id2]) swap(id1, id2); int ans = -1; if(isBlock[id1] && isBlock[id2]){ int idx1 = idx[id1], idx2 = idx[id2]; for(int i = 0; i < (int) bit[idx1].size(); i++){ if(ans != -1) break; if(!(bit[idx1][i] & bit[idx2][i])){ continue; } for(int k = 0; k < 64; k++){ unsigned long long flag1 = bit[idx1][i] & (1ULL << (k % 64)), flag2 = bit[idx2][i] & (1ULL << (k % 64)); if(flag1 && flag2){ ans = i * 64 + k; break; } } } } else if(isBlock[id1] && !isBlock[id2]){ int idx1 = idx[id1]; for(auto x : s[id2]){ if(bit[idx1][x / 64] & (1ULL << (x % 64))){ ans = x; break; } } } else{ for(auto x : s[id1]){ seen[x] = true; } for(auto x : s[id2]){ if(seen[x]){ ans = x; break; } } for(auto x : s[id1]){ seen[x] = false; } } return ans; } // size of intersect set int intersectCount(int id1, int id2){ if(isBlock[id2]) swap(id1, id2); int ans = 0; if(isBlock[id1] && isBlock[id2]){ int idx1 = idx[id1], idx2 = idx[id2]; for(int i = 0; i < (int) bit[idx1].size(); i++){ ans += __builtin_popcountll(bit[idx1][i] & bit[idx2][i]); } } else if(isBlock[id1] && !isBlock[id2]){ int idx1 = idx[id1]; for(auto x : s[id2]){ if(bit[idx1][x / 64] & (1ULL << (x % 64))){ ans++; } } } else{ for(auto x : s[id1]){ seen[x] = true; } for(auto x : s[id2]){ if(seen[x]){ ans++; } } for(auto x : s[id1]){ seen[x] = false; } } return ans; } }; int main(){ ios::sync_with_stdio(false); cin.tie(nullptr); srand(time(NULL)); int l, m, n; cin >> l >> m >> n; vector a(l), b(m); for(int i = 0; i < l; i++){ cin >> a[i]; } for(int i = 0; i < m; i++){ cin >> b[i]; } int q; cin >> q; MergeableSet<300> ms(2, n + q); for(auto x : a) ms.insert(0, x); for(auto x : b) ms.insert(1, x); for(int i = 0; i < q; i++){ cout << ms.intersectCount(0, 1) << "\n"; ms.shift(1, 1); } }