結果
| 問題 |
No.206 数の積集合を求めるクエリ
|
| コンテスト | |
| ユーザー |
|
| 提出日時 | 2024-04-30 05:02:09 |
| 言語 | C++17 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
WA
|
| 実行時間 | - |
| コード長 | 5,860 bytes |
| コンパイル時間 | 2,608 ms |
| コンパイル使用メモリ | 210,624 KB |
| 最終ジャッジ日時 | 2025-02-21 09:49:43 |
|
ジャッジサーバーID (参考情報) |
judge3 / judge4 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 3 |
| other | AC * 27 WA * 1 |
ソースコード
#include <bits/stdc++.h>
using namespace std;
template <typename T, int BLOCK = 500>
struct MergeableSet{
int N, M;
int nxt = 0;
vector<bool> isBlock, seen;
vector<int> idx;
vector<vector<T>> 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(N), 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, T x){
assert(0 <= x && x < M);
if(isBlock[id]){
bit[idx[id]][x / 64] |= 1ULL << (x % 64);
} else{
s[id].emplace_back(x);
if((int) s[id].size() + 1 >= BLOCK){
toBlock(id);
}
}
}
void erase(int id, T x){
assert(0 <= x && x < M);
if(isBlock[id]){
bit[idx[id]][x / 64] &= ~(1ULL << (x % 64));
} else{
vector<T> tmp;
for(auto y : s[id]){
if(x != y){
tmp.emplace_back(y);
}
}
s[id] = tmp;
}
}
void shift(int id, T x){
if(isBlock[id]){
T d = x / 64, m = x % 64;
int siz = bit[idx[id]].size();
vector<unsigned long long> 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<T> 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
T intersect(int id1, int id2){
if(isBlock[id2]) swap(id1, id2);
T 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
T intersectCount(int id1, int id2){
if(isBlock[id2]) swap(id1, id2);
T 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<int, 500> 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);
}
}