#include <iostream>
#include <vector>
#include <string>
using namespace std;
// Struktura opisująca operację tworzenia nowego zbioru
struct Op {
int type; // 1: suma, 2: iloczyn, 3: negacja
int x, y;
};
// Struktura opisująca zapytanie
struct Query {
int x, v, id;
};
// Tablica na wyniki (0 - NIE, 1 - TAK)
bool results[1000005];
// Przechowujemy operacje
Op ops[400005];
// Przechowujemy zapytania pogrupowane po wartości v dla wydajniejszego cache
vector<pair<int, int>> queries_at_v[50005];
// Stan przynależności dla aktualnego bloku 64 wartości v
uint64_t state[450005];
int main() {
// Szybkie I/O
ios_base::sync_with_stdio(false);
cin.tie(NULL);
int n, m, q;
if (!(cin >> n >> m >> q)) return 0;
// Wczytywanie operacji
for (int i = 1; i <= m; ++i) {
cin >> ops[i].type;
if (ops[i].type == 3) {
cin >> ops[i].x;
} else {
cin >> ops[i].x >> ops[i].y;
}
}
// Wczytywanie zapytań i grupowanie ich po wartości v
for (int i = 0; i < q; ++i) {
int x, v;
cin >> x >> v;
queries_at_v[v].push_back({x, i});
}
// Przetwarzamy wartości v w blokach po 64
for (int v_start = 1; v_start <= n; v_start += 64) {
int v_end = min(v_start + 63, n);
// 1. Inicjalizacja stanów dla zbiorów bazowych A_1 do A_n
for (int j = 1; j <= n; ++j) {
uint64_t mask = 0;
for (int v = v_start; v <= v_end; ++v) {
if (v % j == 0) {
mask |= (1ULL << (v - v_start));
}
}
state[j] = mask;
}
// 2. Wykonanie m operacji na bitach (blokowo)
for (int i = 1; i <= m; ++i) {
int current_idx = n + i;
if (ops[i].type == 1) { // Suma
state[current_idx] = state[ops[i].x] | state[ops[i].y];
} else if (ops[i].type == 2) { // Przecięcie
state[current_idx] = state[ops[i].x] & state[ops[i].y];
} else { // Negacja
// Negujemy tylko bity w zakresie aktualnego bloku
state[current_idx] = ~state[ops[i].x];
}
}
// 3. Odczyt wyników dla zapytań z aktualnego zakresu v
for (int v = v_start; v <= v_end; ++v) {
for (auto& query : queries_at_v[v]) {
int set_idx = query.first;
int res_idx = query.second;
if ((state[set_idx] >> (v - v_start)) & 1ULL) {
results[res_idx] = true;
} else {
results[res_idx] = false;
}
}
}
}
// Wypisanie odpowiedzi
for (int i = 0; i < q; ++i) {
cout << (results[i] ? "TAK\n" : "NIE\n");
}
return 0;
}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 | #include <iostream> #include <vector> #include <string> using namespace std; // Struktura opisująca operację tworzenia nowego zbioru struct Op { int type; // 1: suma, 2: iloczyn, 3: negacja int x, y; }; // Struktura opisująca zapytanie struct Query { int x, v, id; }; // Tablica na wyniki (0 - NIE, 1 - TAK) bool results[1000005]; // Przechowujemy operacje Op ops[400005]; // Przechowujemy zapytania pogrupowane po wartości v dla wydajniejszego cache vector<pair<int, int>> queries_at_v[50005]; // Stan przynależności dla aktualnego bloku 64 wartości v uint64_t state[450005]; int main() { // Szybkie I/O ios_base::sync_with_stdio(false); cin.tie(NULL); int n, m, q; if (!(cin >> n >> m >> q)) return 0; // Wczytywanie operacji for (int i = 1; i <= m; ++i) { cin >> ops[i].type; if (ops[i].type == 3) { cin >> ops[i].x; } else { cin >> ops[i].x >> ops[i].y; } } // Wczytywanie zapytań i grupowanie ich po wartości v for (int i = 0; i < q; ++i) { int x, v; cin >> x >> v; queries_at_v[v].push_back({x, i}); } // Przetwarzamy wartości v w blokach po 64 for (int v_start = 1; v_start <= n; v_start += 64) { int v_end = min(v_start + 63, n); // 1. Inicjalizacja stanów dla zbiorów bazowych A_1 do A_n for (int j = 1; j <= n; ++j) { uint64_t mask = 0; for (int v = v_start; v <= v_end; ++v) { if (v % j == 0) { mask |= (1ULL << (v - v_start)); } } state[j] = mask; } // 2. Wykonanie m operacji na bitach (blokowo) for (int i = 1; i <= m; ++i) { int current_idx = n + i; if (ops[i].type == 1) { // Suma state[current_idx] = state[ops[i].x] | state[ops[i].y]; } else if (ops[i].type == 2) { // Przecięcie state[current_idx] = state[ops[i].x] & state[ops[i].y]; } else { // Negacja // Negujemy tylko bity w zakresie aktualnego bloku state[current_idx] = ~state[ops[i].x]; } } // 3. Odczyt wyników dla zapytań z aktualnego zakresu v for (int v = v_start; v <= v_end; ++v) { for (auto& query : queries_at_v[v]) { int set_idx = query.first; int res_idx = query.second; if ((state[set_idx] >> (v - v_start)) & 1ULL) { results[res_idx] = true; } else { results[res_idx] = false; } } } } // Wypisanie odpowiedzi for (int i = 0; i < q; ++i) { cout << (results[i] ? "TAK\n" : "NIE\n"); } return 0; } |
English