Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <iostream>
- #include <string>
- #include <vector>
- using namespace std;
- const int MAX = 2e5;
- struct vertex
- {
- int res;
- int left;
- int right;
- };
- class Segment_Tree
- {
- struct vertex* tree;
- int tree_size;
- int count_numbers;
- std::vector<int> numbers;
- public:
- void build_tree(int v, int tl, int tr);
- int to_deg_of_two(std::vector<int>& numbers, int count_numbers);
- void Initialize(int count_numbers);
- void set(int k, int x);
- int get_min(int node, int a, int b);
- int find_spot(int start_number);
- int free_up(int number);
- void print_tree();
- };
- void Segment_Tree::build_tree(int v, int tl, int tr)
- {
- //////cout << "numbers:" << endl;
- //for (int j = 0; j < this->numbers.size(); ++j)
- // ////cout << numbers[j] << " ";
- //////cout << endl;
- if (tr - tl == 1)
- {
- //////cout << "* tl, tr = " << tl << " " << tr;
- this->tree[v].res = this->numbers[tl];
- this->tree[v].left = tl;
- this->tree[v].right = tr;
- //////cout << " v = " << v << " this->tree[v] = " << this->tree[v].res << endl;
- //print_tree();
- //////cout << "-------------" << endl;
- }
- else
- {
- //////cout << " tl, tr = " << tl << " " << tr << endl;
- int tm = (tl + tr) / 2;
- build_tree(v * 2 + 1, tl, tm);
- build_tree(v * 2 + 2, tm, tr);
- this->tree[v].left = tl;
- this->tree[v].right = tr;
- if (tree[v * 2 + 1].res < tree[v * 2 + 2].res)
- this->tree[v].res = tree[v * 2 + 1].res;
- else
- this->tree[v].res = tree[v * 2 + 2].res;
- //print_tree();
- //////cout << "-------------" << endl;
- //////cout << "v = " << v << " this->tree[v] = " << this->tree[v].res << endl;
- }
- }
- int Segment_Tree::to_deg_of_two(std::vector<int>& numbers, int count_numbers)
- {
- int p = 1;
- while (count_numbers > p)
- p *= 2;
- for (int i = 0; i < p - count_numbers; ++i)
- this->numbers.push_back(MAX);
- return p;
- }
- void Segment_Tree::Initialize(int count_numbers)
- {
- this->count_numbers = count_numbers;
- this->numbers.clear();
- this->numbers.resize(count_numbers);
- for (int i = 1; i <= count_numbers; ++i)
- this->numbers[i-1] = i;
- this->count_numbers = to_deg_of_two(numbers, count_numbers);
- this->tree_size = 2*this->count_numbers-1;
- this->tree = new vertex[tree_size];
- cout << "this->count_numbers = " << this->count_numbers << endl;
- cout << "this->tree_size = " << this->tree_size << endl;
- build_tree(0, 0, this->count_numbers);
- }
- void Segment_Tree::set(int k, int x)
- {
- ////cout << "вызвана функция set от " << k << " " << x << " " << endl;
- int v = this->count_numbers -1 + k;
- ////cout << "v = " << v << endl;
- this->tree[v].res = x;
- //////cout << "this->tree[v] = " << this->tree[v].res << endl;
- while (v > 0)
- {
- v = (v - 1) / 2;
- int l_min = tree[2 * v + 1].res;
- int r_min = tree[2 * v + 2].res;
- //////cout << "l, r " << l_min << " " << r_min << endl;
- (l_min < r_min) ? this->tree[v].res = l_min : this->tree[v].res = r_min;
- }
- //////cout << "end set" << endl;
- //print_tree();
- }
- int Segment_Tree::get_min(int node, int a, int b)
- {
- int l = tree[node].left;
- int r = tree[node].right;
- if (r <= a || l >= b)
- return MAX;
- if (r < b & l >= a)
- return tree[node].res;
- int m1 = get_min(node * 2 + 1, a, b);
- int m2 = get_min(node * 2 + 2, a, b);
- return (m1 < m2) ? m1 : m2;
- }
- int Segment_Tree::find_spot(int start_number)
- {
- int pos = (start_number-1) + (this->tree_size - this->count_numbers);
- cout << "Начинаю искать с места " << start_number << " оно на индексе " << pos << endl;
- //print_tree();
- if (tree[pos].res != MAX)
- {
- set(start_number-1, MAX);
- cout << "Оно свободно, выведу его , и поставлю МАХ " << tree[pos].res << endl;
- //print_tree();
- return start_number;
- }
- else
- {
- cout << "Оно оказалось занято " << endl;
- print_tree();
- int min_num = get_min(0, start_number-1, this->count_numbers+1);
- if (min_num == MAX)
- {
- cout << "НЕ нашёл минимум спрва, ищу слева" << endl;
- min_num = get_min(0, 0, start_number);
- if (min_num == MAX)
- return -1;
- else
- {
- set(min_num - 1, MAX);
- return min_num;
- }
- }
- else
- {
- cout << "нашёл минимум спрва" << endl;
- set(min_num - 1, MAX);
- return min_num;
- }
- }
- }
- int Segment_Tree::free_up(int number)
- {
- int pos = (number-1) + (this->tree_size - this->count_numbers);
- if (tree[pos].res == MAX)
- {
- set(number - 1, number);
- return 0;
- }
- else
- return -2;
- }
- void Segment_Tree::print_tree()
- {
- int k = 2;
- cout << "\ni= " << 0 << " (" << tree[0].left << ";" << tree[0].right << "): " << tree[0].res << endl;
- for (int i=1; i < this->tree_size; ++i)
- {
- if (i == 2*k-1)
- {
- k *= 2;
- cout << endl;
- }
- cout << "i= " << i << " (" << tree[i].left << ";" << tree[i].right << "): " << tree[i].res << "; ";
- }
- cout << endl;
- }
- int main()
- {
- int n, m;
- char s;
- string number;
- cin >> n >> m;
- Segment_Tree tree;
- tree.Initialize(n);
- for (int i = 0; i < m; ++i)
- {
- cin >> s;
- cin >> number;
- int num = stoi(number);
- if (s == '+')
- cout << tree.find_spot(num) << endl;
- else
- cout << tree.free_up(num) << endl;
- }
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment