Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <iostream>
- #include <vector>
- #include <random>
- const int shift = 1e9; // Сдвиг ключа на 1e9, чтобы все были неотрицательными
- const int p = 2e9 + 33; // Простое число, большее макс. знач ключа
- const int multiplier = 3; // O(n) ~ 3n
- std::random_device rand_dev;
- std::mt19937 generator(rand_dev());
- struct vertex
- {
- bool visited = false;
- std::vector<struct adj_vertex> adj_list;
- int list_size = 0;
- int label = 0;
- };
- struct adj_vertex
- {
- int idx;
- int edge_value;
- };
- class FixedSet
- {
- int count_numbers;
- int alpha_a, alpha_b, beta_a, beta_b;
- std::vector<int> set;
- std::vector<int> labels_array;
- int labels_array_size;
- public:
- FixedSet();
- void Initialize(const std::vector<int>& numbers);
- bool Contains(int number) const;
- private:
- int rand_int(int min, int max);
- int uni_hash(long long int a, long long int b, int m, int key) const;
- class Graph
- {
- struct vertex* graph;
- int count_edges;
- int count_vertex;
- public:
- explicit Graph(int count_vertex);
- void addEdge(int i, int j, int key_idx);
- void DFS(int v_idx, int value, bool& flag);
- bool is_correct();
- int get_label(int vertex_idx);
- void clear();
- };
- };
- FixedSet::Graph::Graph(int count_vertex)
- {
- graph = new vertex[count_vertex];
- this->count_edges = 0;
- this->count_vertex = count_vertex;
- }
- int FixedSet::Graph::get_label(int vertex_idx)
- {
- return graph[vertex_idx].label;
- }
- void FixedSet::Graph::clear()
- {
- for (int i = 0; i < (this->count_vertex); ++i)
- {
- graph[i].list_size = 0;
- graph[i].label = 0;
- graph[i].adj_list.clear();
- graph[i].visited = false;
- this->count_edges = 0;
- }
- }
- void FixedSet::Graph::addEdge(int i, int j, int key_idx)
- {
- adj_vertex buff;
- buff.idx = j;
- buff.edge_value = key_idx;
- graph[i].adj_list.push_back(buff);
- buff.idx = i;
- graph[j].adj_list.push_back(buff);
- graph[i].list_size++;
- graph[j].list_size++;
- this->count_edges++;
- }
- void FixedSet::Graph::DFS(int v_idx, int value, bool& flag)
- {
- if (flag)
- {
- graph[v_idx].visited = true;
- graph[v_idx].label = value;
- vertex u;
- std::vector<struct adj_vertex> curr_list = graph[v_idx].adj_list;
- int u_idx, u_value, edge_value;
- for (int i = 0; i < graph[v_idx].list_size; ++i)
- {
- u_idx = curr_list[i].idx;
- u = graph[u_idx];
- edge_value = curr_list[i].edge_value;
- if (!(u.visited))
- {
- u_value = edge_value - value;
- DFS(u_idx, u_value, flag);
- }
- if (((graph[u_idx].label + graph[v_idx].label) % (this->count_edges)) != edge_value)
- {
- flag = false;
- break;
- }
- }
- }
- }
- bool FixedSet::Graph::is_correct()
- {
- bool flag = true;
- for (int i = 0; i < (this->count_vertex); ++i)
- {
- if (!graph[i].visited)
- DFS(i, 0, flag);
- if (!flag)
- return false;
- }
- return true;
- }
- FixedSet::FixedSet()
- {
- this->count_numbers = 0;
- this->labels_array_size = 0;
- }
- int FixedSet::rand_int(int min, int max)
- {
- std::uniform_int_distribution<int> distr(min, max);
- return distr(generator);
- }
- int FixedSet::uni_hash(long long int a, long long int b, int m, int key) const
- {
- return ((a * key + b) % p) % labels_array_size;
- }
- void FixedSet::Initialize(const std::vector<int>& numbers)
- {
- set.clear();
- labels_array.clear();
- this->count_numbers = 0;
- this->labels_array_size = 0;
- if (!numbers.empty())
- {
- int n = numbers.size();
- int m = multiplier * n;
- this->count_numbers = n;
- this->labels_array_size = m;
- Graph graph(m);
- for (int i = 0; i < n; ++i)
- set.push_back(numbers[i] + shift);
- long long int alpha_k, beta_k;
- bool flag = false;
- while (!flag)
- {
- graph.clear();
- this->alpha_a = rand_int(1, p - 1);
- this->alpha_b = rand_int(0, p - 1);
- this->beta_a = rand_int(1, p - 1);
- this->beta_b = rand_int(0, p - 1);
- for (int key_idx = 0; key_idx < n; ++key_idx)
- {
- alpha_k = uni_hash(alpha_a, alpha_b, m, numbers[key_idx] + shift);
- beta_k = uni_hash(beta_a, beta_b, m, numbers[key_idx] + shift);
- graph.addEdge(alpha_k, beta_k, key_idx);
- }
- flag = graph.is_correct();
- }
- for (int i = 0; i < m; ++i)
- labels_array.push_back(graph.get_label(i));
- }
- }
- bool FixedSet::Contains(int number) const
- {
- if (this->labels_array_size == 0)
- return false;
- int m = this->labels_array_size;
- int n = this->count_numbers;
- int hash_alpha = uni_hash(this->alpha_a, this->alpha_b, m, number + shift);
- int hash_beta = uni_hash(this->beta_a, this->beta_b, m, number + shift);
- int idx = (labels_array[hash_alpha] + labels_array[hash_beta]) % n;
- return (0 <= idx && this->set[idx] == (number + shift));
- }
- std::vector<int> ReadSequence()
- {
- size_t size;
- std::cin >> size;
- std::vector<int> sequence(size);
- for (auto& current : sequence)
- {
- std::cin >> current;
- }
- return sequence;
- }
- std::vector<bool> PerformRequests(const std::vector<int>& requests, const FixedSet& set)
- {
- std::vector<bool> request_answers;
- request_answers.reserve(requests.size());
- for (int request : requests)
- {
- request_answers.push_back(set.Contains(request));
- }
- return request_answers;
- }
- void PrintRequestsResponse(const std::vector<bool>& request_answers)
- {
- for (bool answer : request_answers)
- {
- std::cout << (answer ? "Yes" : "No") << "\n";
- }
- }
- int main()
- {
- auto numbers = ReadSequence();
- auto requests = ReadSequence();
- FixedSet set;
- set.Initialize(numbers);
- PrintRequestsResponse(PerformRequests(requests, set));
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment