Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <iostream>
- #include <vector>
- #include <stdexcept>
- #include <cstring>
- #include <random>
- #include <utility>
- #include <ctime>
- const int p = 2000000011;
- const long long int shift = 1e9; // Чтобы все ключи были неотрицательные
- const int c = 3;
- std::random_device rand_dev;
- std::mt19937 generator(rand_dev());
- int rand()
- { // NOLINT
- throw std::runtime_error("Don't use rand");
- }
- int rand_int(int min, int max)
- {
- std::uniform_int_distribution<int> distr(min, max);
- return distr(generator);
- }
- long long int uni_hash(long long int a, long long int b, int m, int key)
- {
- return ((a * key + b) % p) % m;
- }
- struct vertex
- {
- bool visited = false;
- std::vector<struct adj_vertex> adj_list;
- int list_size = 0;
- long long int label = -1;
- };
- struct adj_vertex
- {
- int idx;
- int edge_value;
- };
- class Graph
- {
- vertex* G;
- int size;
- public:
- explicit Graph(int n);
- int get_size();
- void addEdge(int i, int j, int key_idx);
- void DFS(int v_idx, int value, bool& flag);
- bool is_correct();
- long long int get_label(int number_vertex);
- };
- Graph::Graph(int n)
- {
- G = new vertex[n];
- size = n;
- }
- long long int Graph::get_label(int number_vertex)
- {
- return G[number_vertex].label;
- }
- int Graph::get_size()
- {
- return this->size;
- }
- void Graph::addEdge(int i, int j, int key_idx)
- {
- adj_vertex buff;
- buff.idx = j;
- buff.edge_value = key_idx;
- G[i].adj_list.push_back(buff);
- buff.idx = i;
- G[j].adj_list.push_back(buff);
- G[i].list_size++;
- G[j].list_size++;
- }
- void Graph::DFS(int v_idx, int value, bool& flag)
- {
- if (flag)
- {
- G[v_idx].visited = true;
- G[v_idx].label = value;
- vertex u;
- std::vector<struct adj_vertex> curr_list = G[v_idx].adj_list;
- int u_idx, val, edge_value;
- for (int i = 0; i < G[v_idx].list_size; ++i)
- {
- u_idx = curr_list[i].idx;
- u = G[u_idx];
- edge_value = curr_list[i].edge_value;
- if (!(u.visited))
- {
- val = edge_value - value;
- DFS(u_idx, val, flag);
- }
- if (((G[u_idx].label + G[v_idx].label) % (this->size)) != edge_value)
- {
- flag = false;
- break;
- }
- }
- }
- }
- bool Graph::is_correct()
- {
- bool flag = true;
- for (int i = 0; i < this->size; ++i)
- {
- if (!G[i].visited)
- DFS(i, 0, flag);
- if (!flag)
- return false;
- }
- return true;
- }
- class FixedSet
- {
- int count_numbers;
- int size;
- long long int alpha_a, alpha_b, beta_a, beta_b;
- std::vector<int> table;
- std::vector<int> A;
- public:
- FixedSet();
- void Initialize(const std::vector<int>& numbers);
- bool Contains(int number) const;
- };
- FixedSet::FixedSet()
- {
- this->count_numbers = 0;
- this->size = 0;
- }
- void FixedSet::Initialize(const std::vector<int>& numbers)
- {
- table.clear();
- A.clear();
- if (!numbers.empty())
- {
- this->count_numbers = numbers.size();
- this->size = (this->count_numbers) * c;
- int n = this->count_numbers;
- int m = this->size;
- this->A.resize(m);
- for (int i = 0; i < n; ++i)
- table.push_back(numbers[i] + shift);
- long long int alpha_k, beta_k;
- bool flag = false;
- while (!flag)
- {
- Graph g(m);
- 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 i = 0; i < n; ++i)
- {
- alpha_k = uni_hash(alpha_a, alpha_b, m, numbers[i] + shift);
- beta_k = uni_hash(beta_a, beta_b, m, numbers[i] + shift);
- g.addEdge(alpha_k, beta_k, i);
- }
- if (g.is_correct())
- {
- flag = true;
- for (int i = 0; i < m; ++i)
- this->A[i] = g.get_label(i);
- }
- }
- }
- }
- bool FixedSet::Contains(int number) const
- {
- if (this->size == 0)
- return false;
- int m = this->size;
- 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 = (A[hash_alpha] + A[hash_beta]) % m;
- if (0 <= idx < m)
- return (this->table[idx] == number + shift);
- return false;
- }
- 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(int argc, char** argv)
- {
- std::ios::sync_with_stdio(false);
- 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
Advertisement