Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <iostream>
- #include <vector>
- #include <algorithm>
- using namespace std;
- using ll = long long;
- template <class T>
- class SegmentTree
- {
- private:
- struct Node
- {
- T modify;
- T query;
- };
- int size;
- T q_neutral;
- T m_neutral;
- T(*query)(const T&, const T&);
- T(*modify)(const T&, const T&);
- vector<Node> tree;
- void build(const vector<T>& a, int v, int left, int right)
- {
- if (left + 1 == right)
- tree[v].query = a[left];
- else
- {
- int mid = (left + right) >> 1;
- build(a, 2 * v, left, mid);
- build(a, 2 * v + 1, mid, right);
- tree[v].query = query(tree[2 * v].query, tree[2 * v + 1].query);
- }
- }
- void propagate(int v, int left, int right)
- {
- if (left + 1 == right || tree[v].modify == m_neutral) return;
- tree[2 * v].modify = modify(tree[2 * v].modify, tree[v].modify);
- tree[2 * v].query = modify(tree[2 * v].query, tree[v].modify);
- tree[2 * v + 1].modify = modify(tree[2 * v + 1].modify, tree[v].modify);
- tree[2 * v + 1].query = modify(tree[2 * v + 1].query, tree[v].modify);
- tree[v].modify = m_neutral;
- }
- T getQuery(int v, int start, int end, int left, int right)
- {
- propagate(v, left, right);
- if (end <= left || right <= start)
- return q_neutral;
- if (start <= left && right <= end)
- return tree[v].query;
- else
- {
- int mid = (left + right) >> 1;
- return query(getQuery(2 * v, start, end, left, mid),
- getQuery(2 * v + 1, start, end, mid, right));
- }
- }
- void update(int v, const T& x, int start, int end, int left, int right)
- {
- propagate(v, left, right);
- if (end <= left || right <= start)
- return;
- if (start <= left && right <= end)
- {
- tree[v].modify = modify(tree[v].modify, x);
- tree[v].query = modify(tree[v].query, x);
- return;
- }
- else
- {
- int mid = (left + right) >> 1;
- update(2 * v, x, start, end, left, mid);
- update(2 * v + 1, x, start, end, mid, right);
- tree[v].query = query(tree[2 * v].query, tree[2 * v + 1].query);
- }
- }
- void get_init_vec_help(vector<T>& vec, int v, int left, int right)
- {
- if (left + 1 == right)
- vec[left] = tree[v].query;
- else
- {
- int mid = (left + right) >> 1;
- get_init_vec_help(vec, 2 * v, left, mid);
- get_init_vec_help(vec, 2 * v + 1, mid, right);
- }
- }
- public:
- SegmentTree(int n, T(*_query)(const T&, const T&), T(*_modify)(const T&, const T&), const T& _q_neutral = T(), const T& _m_neutral = T())
- : size(n)
- , q_neutral(_q_neutral)
- , m_neutral(_m_neutral)
- , query(_query)
- , modify(_modify)
- , tree(size << 2, { m_neutral , q_neutral })
- { }
- SegmentTree(const vector<T>& vec, T(*_query)(const T&, const T&), T(*_modify)(const T&, const T&), const T& _q_neutral = T(), const T& _m_neutral = T())
- : SegmentTree(vec.size(), _query, _modify, _q_neutral, _m_neutral)
- {
- build(vec, 1, 0, size);
- }
- SegmentTree<T> operator =(const SegmentTree<T>& Tree)
- {
- if (this == &Tree) return *this;
- size = Tree.size;
- tree = Tree.tree;
- q_neutral = Tree.q_neutral;
- m_neutral = Tree.m_neutral;
- modify = Tree.modify;
- query = Tree.query;
- return *this;
- }
- SegmentTree<T> merge(SegmentTree<T>& Tree)
- {
- if (q_neutral != Tree.q_neutral || m_neutral != Tree.m_neutral) return *this;
- Tree.propagate(1, 0, Tree.size);
- propagate(1, 0, size);
- vector<T> init_vec = get_init_vec();
- vector<T> Tree_init_vec = Tree.get_init_vec();
- init_vec.insert(init_vec.end(), Tree_init_vec.begin(), Tree_init_vec.end());
- SegmentTree<T> rez(init_vec, query, modify, q_neutral, m_neutral);
- return rez;
- }
- SegmentTree<T> merge(const SegmentTree<T>& Tree)
- {
- if (q_neutral != Tree.q_neutral || m_neutral != Tree.m_neutral) return *this;
- Tree.propagate(1, 0, size);
- propagate(1, 0, size);
- int len = max(size, Tree.size) - min(size, Tree.size);
- vector<T> sup_vec(len, 0);
- SegmentTree<T> sup_tree(sup_vec, query, modify, q_neutral, m_neutral);
- }
- void update(int start, int end, const T& x)
- {
- update(1, x, start, end + 1, 0, size);
- }
- const T& getQuery(int start, int end)
- {
- return getQuery(1, start, end + 1, 0, size);
- }
- vector<T> get_init_vec()
- {
- vector<T> result(size, 0);
- get_init_vec_help(result, 1, 0, size);
- return result;
- }
- template <class T>
- friend ostream& operator << (ostream& out, const SegmentTree<T>& Tree);
- };
- template <class T>
- ostream& operator << (ostream& out, const SegmentTree<T>& Tree)
- {
- if (out)
- {
- for (auto it : Tree.tree)
- {
- cout << it.query << " " << it.modify << '\n';
- }
- }
- return out;
- }
- template <class T>
- T modify(const T& a, const T& b)
- {
- if (b == 1) return a;
- return b;
- }
- template <class T>
- T query(const T& a, const T& b)
- {
- return min(a,b);
- }
- int main()
- {
- vector<ll> vec = { 2,3,4,1,5,6 };
- vector<ll> vec2 = { 2,11,4,5,20 };
- ll(*ptr_modify)(const ll&, const ll&) = &modify;
- ll(*ptr_query)(const ll&, const ll&) = &query;
- SegmentTree<ll> tree(vec, ptr_query, ptr_modify, LLONG_MAX, 1);
- SegmentTree<ll> tree2(vec2, ptr_query, ptr_modify, LLONG_MAX, 1);
- cout << tree.getQuery(0, 5) << '\n';
- tree.update(0, 5, 2);
- cout << tree.getQuery(0, 5) << '\n';
- tree.update(0, 5, 2);
- cout << tree.getQuery(0, 5) << '\n';
- vector<ll> init = tree.get_init_vec();
- /*cout << '\n';
- for (ll it : vec)
- cout << it << " ";
- cout << '\n' << tree;*/
- //cout << tree2.getQuery(0, 5) << '\n';
- //SegmentTree<ll> merge_tree = tree.merge(tree2);
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement