結果
問題 | No.206 数の積集合を求めるクエリ |
ユーザー | dyktr_06 |
提出日時 | 2024-04-30 05:16:07 |
言語 | C++17 (gcc 12.3.0 + boost 1.83.0) |
結果 |
AC
|
実行時間 | 1,836 ms / 7,000 ms |
コード長 | 6,088 bytes |
コンパイル時間 | 2,572 ms |
コンパイル使用メモリ | 218,680 KB |
実行使用メモリ | 6,944 KB |
最終ジャッジ日時 | 2024-04-30 05:16:27 |
合計ジャッジ時間 | 16,159 ms |
ジャッジサーバーID (参考情報) |
judge2 / judge3 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 2 ms
6,812 KB |
testcase_01 | AC | 2 ms
6,940 KB |
testcase_02 | AC | 2 ms
6,940 KB |
testcase_03 | AC | 2 ms
6,940 KB |
testcase_04 | AC | 1 ms
6,940 KB |
testcase_05 | AC | 2 ms
6,940 KB |
testcase_06 | AC | 2 ms
6,944 KB |
testcase_07 | AC | 2 ms
6,940 KB |
testcase_08 | AC | 2 ms
6,940 KB |
testcase_09 | AC | 2 ms
6,940 KB |
testcase_10 | AC | 2 ms
6,940 KB |
testcase_11 | AC | 2 ms
6,940 KB |
testcase_12 | AC | 4 ms
6,940 KB |
testcase_13 | AC | 4 ms
6,944 KB |
testcase_14 | AC | 3 ms
6,940 KB |
testcase_15 | AC | 2 ms
6,944 KB |
testcase_16 | AC | 2 ms
6,940 KB |
testcase_17 | AC | 18 ms
6,940 KB |
testcase_18 | AC | 10 ms
6,944 KB |
testcase_19 | AC | 16 ms
6,940 KB |
testcase_20 | AC | 10 ms
6,944 KB |
testcase_21 | AC | 12 ms
6,940 KB |
testcase_22 | AC | 12 ms
6,944 KB |
testcase_23 | AC | 16 ms
6,940 KB |
testcase_24 | AC | 1,823 ms
6,944 KB |
testcase_25 | AC | 1,834 ms
6,944 KB |
testcase_26 | AC | 1,795 ms
6,940 KB |
testcase_27 | AC | 1,140 ms
6,940 KB |
testcase_28 | AC | 1,824 ms
6,944 KB |
testcase_29 | AC | 1,836 ms
6,940 KB |
testcase_30 | AC | 1,796 ms
6,940 KB |
ソースコード
#include <bits/stdc++.h> using namespace std; template <int BLOCK = 250> struct MergeableSet{ int N, M; int nxt = 0; vector<bool> isBlock, seen; vector<int> idx; vector<vector<int>> s; vector<vector<unsigned long long>> 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<unsigned long long> 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<int> 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 siz = bit[idx[id]].size(); vector<unsigned long long> emp(siz); for(int i = (int) siz - 1; i >= 0; i--){ int j = i + (x / 64); unsigned long long tmp1 = bit[idx[id]][i], tmp2 = bit[idx[id]][i]; tmp1 <<= (x % 64); tmp2 >>= 64 - (x % 64); 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<int> 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<unsigned long long> 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<int> 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<250> 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); } }