Cod sursa(job #2054556)

Utilizator mlc_oficialBoris Barca mlc_oficial Data 2 noiembrie 2017 09:11:10
Problema Arbori de intervale Scor 30
Compilator cpp Status done
Runda Arhiva educationala Marime 4.84 kb
//#pragma GCC optimize("Ofast")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
#include <bits/stdc++.h>

using namespace std;

template<typename T>
class LazySegmentTree {
public:
    LazySegmentTree(const int _n = 0) : delta(2 * _n), tree(2 * _n), n(_n) { 
        for (int i = 0; i < n; i += 1) {
            tree[i + n] = InitValue();
        }
        for (int i = n - 1; i > 0; i -= 1) {
            tree[i] = Combine(tree[i << 1], tree[(i << 1) | 1]);
        }
        fill(delta.begin(), delta.end(), NeutralDelta());
    }
    
    LazySegmentTree(const vector<T>& values) : delta(2 * values.size()), tree(2 * values.size()), n(static_cast<int>(values.size())) { 
        for (int i = 0; i < n; i += 1) {
            tree[i + n] = values[i];
        }
        for (int i = n - 1; i > 0; i -= 1) {
            tree[i] = Combine(tree[i << 1], tree[(i << 1) | 1]);
        }
        fill(delta.begin(), delta.end(), NeutralDelta());
    }
    
    T Query(int from, int to) {
        from += n;
        to += n;
        PushDelta(from);
        PushDelta(to);
        
        int segment_length = 1;
        T res = InitValue();
        while (from <= to) {
            if (from & 1) {
                res = Combine(res, CombineNodeWithDelta(from, segment_length));
            }
            if (~to & 1) {
                res = Combine(CombineNodeWithDelta(to, segment_length), res);
            }
            
            from = (from + 1) >> 1;
            to = (to - 1) >> 1;
            segment_length <<= 1;
        }
        return res;
    }
    
    void Update(int from, int to, const T by) {
        from += n;
        to += n;
        PushDelta(from);
        PushDelta(to);
        
        for (int i = from, j = to; i <= j; i = (i + 1) >> 1, j = (j - 1) >> 1) {
            if (i & 1) {
                delta[i] = CombineDeltas(delta[i], by);
            }
            if (~j & 1) {
                delta[j] = CombineDeltas(delta[j], by);
            }
        }
        for (int i = from >> 1, segment_length = 1; i > 0; i >>= 1, segment_length <<= 1) {
            tree[i] = Combine(CombineNodeWithDelta(i << 1, segment_length), 
                              CombineNodeWithDelta((i << 1) | 1, segment_length));
        }
        for (int i = to >> 1, segment_length = 1; i > 0; i >>= 1, segment_length <<= 1) {
            tree[i] = Combine(CombineNodeWithDelta(i << 1, segment_length), 
                              CombineNodeWithDelta((i << 1) | 1, segment_length));
        }
    }
private:
    static T Modify(const T a, const T b) { 
        return b; 
    }
    
    static T Combine(const T a, const T b) {
        return max(a, b);
    }
    
    static T NeutralDelta() {
        return 0;
    }
    
    static T InitValue() {
        return 0;
    }
    
    static T CombineSegmentWithDelta(const T delta, const int segment_length) {
        if (delta == NeutralDelta()) {
            return NeutralDelta();
        }
        
        // int result = delta;
        // for (int i = 1; i < segment_length; i += 1) result = Combine(result, delta);
        // return result;
        return delta;
    }
    
    static T CombineValueWithDelta(const T value, const T delta) {
        if (delta == NeutralDelta()) {
            return value;
        }
        
        return Modify(value, delta);
    }
    
    static T CombineDeltas(const T delta_1, const T delta_2) {
        if (delta_1 == NeutralDelta()) {
            return delta_2;
        }
        if (delta_2 == NeutralDelta()) {
            return delta_1;
        }
        
        return Modify(delta_1, delta_2);
    }
    
    T CombineNodeWithDelta(const int node, const int segment_length) const {
        return CombineValueWithDelta(tree[node], CombineSegmentWithDelta(delta[node], segment_length)); 
    }
    
    void PushDelta(int node) {
        for (int d = __lg(node) - 1; d >= 0; d -= 1) {
            const int where = node >> d;
            tree[where >> 1] = CombineNodeWithDelta(where >> 1, 1 << (d + 1));
            delta[where ^ 0] = CombineDeltas(delta[where ^ 0], delta[where >> 1]);
            delta[where ^ 1] = CombineDeltas(delta[where ^ 1], delta[where >> 1]);
            delta[where>> 1] = NeutralDelta();
        }
    }
    
    vector<T> delta, tree;
    int n;
};

int main() {
    ifstream cin("arbint.in");
    ofstream cout("arbint.out");
    cin.tie(0);
    ios_base::sync_with_stdio(false);
    
    int n, q; cin >> n >> q;
    vector<int> v(n);
    for (auto& x : v) {
        cin >> x;
    }
    
    LazySegmentTree<int> tree(v);
    while (q--> 0) {
        int type; cin >> type;
        if (type == 0) {
            int left, right; cin >> left >> right; left -= 1; right -= 1;
            cout << tree.Query(left, right) << '\n';
        } else {
            int pos, value; cin >> pos >> value; pos -= 1;
            tree.Update(pos, pos, value);
        }
    }
    return 0;
}