easy to understand segment tree solution. 
IntuitionLet d[x] be the distance of the next obstacle after x.For each query of type 2, we just need to check if max(d[0], d[1], d[2], …d[x - sz]) > sz.Approac
# Intuition
Let d[x] be the distance of the next obstacle after x.

For each query of type 2, we just need to check if max(d[0], d[1], d[2], …d[x - sz]) > sz.

# Approach
Use segment tree to maintain d[x].
The main idea is to use a set so that I can find previous and next index of a point for query type 1. 

initally in the set we have 0, maxn. let's say the set looks like [0, 3, 8, maxn] after adding 8, and 3. 
If we add point 5, then we need to update the segment tree for point 3, and 5. We need to update the point 3, because we will add 5 infront of it. 




# Complexity
- Time complexity:
$$O(n*logn)$$

- Space complexity:
$$O(n)$$

# Code
```cpp []
// Let d[x] be the distance of the next obstacle after x.

// For each query of type 2, we just need to check if max(d[0], d[1], d[2], …d[x - sz]) > sz.

// Use segment tree to maintain d[x].

const int maxn = 50005;

int tree[4 * (maxn+1)];

void build(int node, int beg, int end) {
    if(beg == end) {
        tree[node] = 0;
        return ;
    }
    int mid = ( beg + end) / 2;
    int lc = node * 2;
    int rc = lc + 1;
    build(lc, beg, mid);
    build(rc, mid + 1, end);
    tree[node] = max(tree[lc], tree[rc]);
}

void update(int node, int beg, int end, int i, int val) {
    if(i < beg || i > end) return; 
    if(beg == i && end == i) {
        tree[node] = val;
        return;
    }
    int lc = node * 2;
    int rc = lc + 1;
    int mid = (beg + end) / 2;
    if(i<=mid)
        update(lc, beg, mid, i, val);
    else update(rc, mid + 1, end, i, val);
    tree[node] = max(tree[lc], tree[rc]);
}

int query(int node, int beg, int end, int i, int j) {
    if(i > end || j < beg) return 0; // i to j is out of beg to end
    if(beg >= i && end <= j) return tree[node];

    int lc = node * 2;
    int rc = lc + 1;
    int mid = (beg + end)/2;
    int l = query(lc, beg, mid, i, j);
    int r = query(rc, mid + 1, end, i, j);
    return max(l, r);
}



class Solution {
public:
    vector<bool> getResults(vector<vector<int>>& queries) {
    //    build(1, 0, maxn); // we can skip building the tree since all inital value is 0.
    memset(tree, 0, sizeof tree);
    
    update(1, 0, maxn, 0, maxn); // we set maxn at 0, because initally we can place block of any size 

        set<int> points;
        // we add the inital vlues as 0 and maxn as they represent end to end. 
        points.insert(0); 
        points.insert(maxn);

        vector<bool> ret;
       for(auto q:queries) {
            if(q.size() == 2) {
                add(q[1], points);
            }else {
                ret.push_back(assign(q[1], q[2])); 
            }
       }
       return ret;

    }

    bool assign(int p, int sz) {
        int ret = query(1, 0, maxn, 0, p-sz);
        return ret >= sz;
    }

    void add(int p, set<int> &points) {
        // we add the current point 
        points.insert(p);

        // after adding the point, we adjust the point on left.
        // the value on the left point will be (p - l)
        // and the value on the point will be r - p

        auto it = points.upper_bound(p); // it is p
        int r = *it; 
        it--; // p
        it--; // the point before p
        int l = *it; 

        

        int leftValue = p - l;
        int pValue = r - p;
        update(1, 0, maxn, l, leftValue);
        update(1, 0, maxn, p, pValue);
    }

};
```
['C++']