#include <bits/stdc++.h>
using namespace std;
class SegTree {
 public:
  vector<long long> mat;
  vector<bool> has_data;
  vector<long long> lazy;
  long long max_res;
  int sz;
  SegTree(int len) {
    max_res = 6000000000000000000ll;
    int n = len * 4;
    mat = vector<long long>(n, max_res);
    lazy = vector<long long>(n, 0);
    has_data = vector<bool>(n, false);
    sz = n;
  }
  long long bulk_add(int idx, int stpnt, int endpnt, int target_start,
                     int target_end, long long val) {
    if (stpnt > endpnt) return max_res;
    if (stpnt == endpnt) {
      if (has_data[idx] == false) return max_res;
      if (stpnt > target_end || endpnt < target_start) {
        return mat[idx];
      }
      mat[idx] += val;
      lazy[idx] = 0;
      return mat[idx];
    }
    push_down(idx);
    if (has_data[idx] == false) return max_res;
    if (stpnt > target_end || endpnt < target_start) {
      if (has_data[idx] == false) {
        return max_res;
      }
      return mat[idx];
    }
    if (stpnt >= target_start && endpnt <= target_end) {
      mat[idx] += val;
      lazy[idx] += val;
      return mat[idx];
    }
    int mid = (stpnt + endpnt) / 2;
    return mat[idx] = min(
               bulk_add(idx * 2 + 1, stpnt, mid, target_start, target_end, val),
               bulk_add(idx * 2 + 2, mid + 1, endpnt, target_start, target_end,
                        val));
  }
  long long query_range(int idx, int stpnt, int endpnt, int target_start,
                        int target_end) {
    if (stpnt > endpnt) return max_res;
    if (stpnt == endpnt) {
      if (has_data[idx] == false || stpnt > target_end || endpnt < target_start)
        return max_res;
      return mat[idx];
    }
    push_down(idx);
    if (has_data[idx] == false) return max_res;
    if (stpnt > target_end || endpnt < target_start) return max_res;
    if (stpnt >= target_start && endpnt <= target_end) {
      return mat[idx];
    }
    int mid = (stpnt + endpnt) / 2;
    long long left =
        query_range(idx * 2 + 1, stpnt, mid, target_start, target_end);
    long long right =
        query_range(idx * 2 + 2, mid + 1, endpnt, target_start, target_end);
    long long res = min(left, right);
    return res;
  }
  pair<long long, bool> insert_val(int idx, int stpnt, int endpnt, int target,
                                   long long val) {
    if (stpnt > endpnt) return make_pair(max_res, false);
    if (stpnt == endpnt) {
      if (stpnt > target || endpnt < target) {
        if (has_data[idx] == false) return make_pair(max_res, has_data[idx]);
        return make_pair(mat[idx], has_data[idx]);
      }
      mat[idx] = val;
      has_data[idx] = true;
      lazy[idx] = 0;
      return make_pair(val, true);
    }
    push_down(idx);
    if (stpnt > target || endpnt < target) {
      if (has_data[idx] == false) {
        return make_pair(max_res, false);
      }
      return make_pair(mat[idx], has_data[idx]);
    }
    int mid = (stpnt + endpnt) / 2;
    pair<long long, bool> left =
        insert_val(idx * 2 + 1, stpnt, mid, target, val);
    pair<long long, bool> right =
        insert_val(idx * 2 + 2, mid + 1, endpnt, target, val);
    mat[idx] = min(left.first, right.first);
    has_data[idx] = (left.second || right.second);
    return make_pair(mat[idx], has_data[idx]);
  }
  pair<long long, bool> delete_val(int idx, int stpnt, int endpnt, int target) {
    if (stpnt > endpnt) return make_pair(max_res, false);
    if (stpnt == endpnt) {
      if (stpnt > target || endpnt < target) {
        if (has_data[idx] == false) return make_pair(max_res, false);
        return make_pair(mat[idx], has_data[idx]);
      }
      mat[idx] = max_res;
      has_data[idx] = false;
      lazy[idx] = 0;
      return make_pair(max_res, false);
    }
    push_down(idx);
    if (stpnt > target || endpnt < target) {
      if (has_data[idx] == false) {
        return make_pair(max_res, false);
      }
      return make_pair(mat[idx], has_data[idx]);
    }
    int mid = (stpnt + endpnt) / 2;
    pair<long long, bool> left = delete_val(idx * 2 + 1, stpnt, mid, target);
    pair<long long, bool> right =
        delete_val(idx * 2 + 2, mid + 1, endpnt, target);
    mat[idx] = min(left.first, right.first);
    has_data[idx] = (left.second || right.second);
    if (has_data[idx] == false) {
      mat[idx] = max_res;
    }
    return make_pair(mat[idx], has_data[idx]);
  }
  void push_down(int idx) {
    if (has_data[idx] == false) {
      mat[idx] = max_res;
      lazy[idx] = 0;
      return;
    }
    int left_idx = idx * 2 + 1;
    int right_idx = idx * 2 + 2;
    if (has_data[left_idx]) {
      mat[left_idx] += lazy[idx];
      lazy[left_idx] += lazy[idx];
    }
    if (has_data[right_idx]) {
      mat[right_idx] += lazy[idx];
      lazy[right_idx] += lazy[idx];
    }
    lazy[idx] = 0;
  }
};
void test_seg_tree() {
  SegTree s(3);
  long long val_0, val_1, val_2;
  s.insert_val(0, 0, 2, 0, 0);
  cout << "starting:" << endl;
  val_0 = s.query_range(0, 0, 2, 0, 0);
  cout << "val_0: " << val_0 << endl;
  s.insert_val(0, 0, 2, 1, 2);
  cout << "starting:" << endl;
  val_0 = s.query_range(0, 0, 2, 0, 0);
  cout << "starting:" << endl;
  val_1 = s.query_range(0, 0, 2, 1, 1);
  cout << "val_0: " << val_0 << " val_1: " << val_1 << endl;
  s.insert_val(0, 0, 2, 2, 3);
  cout << "starting:" << endl;
  val_0 = s.query_range(0, 0, 2, 0, 0);
  cout << "starting:" << endl;
  val_1 = s.query_range(0, 0, 2, 1, 1);
  cout << "starting:" << endl;
  val_2 = s.query_range(0, 0, 2, 2, 2);
  cout << "val_0: " << val_0 << " val_1: " << val_1 << " val_2: " << val_2
       << endl;
}
int main() {
  int q;
  scanf("%d", &q);
  vector<vector<long long> > inp(q, vector<long long>(4, 0));
  set<long long> all_t;
  set<long long> cur_t;
  map<long long, int> t_idx;
  map<int, long long> idx_to_t;
  map<long long, long long> t_s;
  for (int i = 0; i < q; i++) {
    int type;
    scanf("%d", &type);
    if (type == 1) {
      long long t, s;
      scanf("%lld %lld", &t, &s);
      inp[i][0] = type;
      inp[i][1] = t;
      inp[i][2] = s;
      all_t.insert(t);
    } else if (type == 2) {
      long long t;
      scanf("%lld", &t);
      inp[i][0] = type;
      inp[i][1] = t;
    } else {
      long long l, r, v;
      scanf("%lld %lld %lld", &l, &r, &v);
      inp[i][0] = type;
      inp[i][1] = l;
      inp[i][2] = r;
      inp[i][3] = v;
    }
  }
  SegTree tree((int)all_t.size());
  int max_t_len = (int)all_t.size();
  int cnt = 0;
  for (set<long long>::iterator it = all_t.begin(); it != all_t.end(); it++) {
    t_idx[*it] = cnt;
    idx_to_t[cnt] = *it;
    cnt++;
  }
  for (int i = 0; i < inp.size(); i++) {
    if (inp[i][0] == 1) {
      long long t, s;
      t = inp[i][1];
      s = inp[i][2];
      int cur_t_idx = t_idx[t];
      set<long long>::iterator it = cur_t.upper_bound(t);
      long long prev_val = 0;
      long long prev_s = 0;
      long long prev_t = 0;
      if (it != cur_t.begin()) {
        set<long long>::iterator it2 = it;
        it2--;
        prev_t = *it2;
        prev_s = t_s[prev_t];
        int idx = t_idx[prev_t];
        prev_val = tree.query_range(0, 0, max_t_len - 1, idx, idx);
      }
      long long val_to_insert = prev_val + (t - prev_t) * prev_s;
      tree.insert_val(0, 0, max_t_len - 1, cur_t_idx, val_to_insert);
      if (it != cur_t.end()) {
        long long next_t = *it;
        int idx = t_idx[next_t];
        long long next_val = tree.query_range(0, 0, max_t_len - 1, idx, idx);
        long long updated_val = val_to_insert + (next_t - t) * s;
        long long diff = updated_val - next_val;
        tree.bulk_add(0, 0, max_t_len - 1, idx, max_t_len - 1, diff);
      }
      cur_t.insert(t);
      t_s[t] = s;
    } else if (inp[i][0] == 2) {
      long long t;
      t = inp[i][1];
      int cur_t_idx = t_idx[t];
      set<long long>::iterator it = cur_t.upper_bound(t);
      long long prev_val = 0;
      long long prev_s = 0;
      long long prev_t = 0;
      if (it != cur_t.begin()) {
        set<long long>::iterator it2 = it;
        it2--;
        if (it2 != cur_t.begin()) {
          it2--;
          prev_t = *it2;
          prev_s = t_s[prev_t];
          int idx = t_idx[prev_t];
          prev_val = tree.query_range(0, 0, max_t_len - 1, idx, idx);
        }
      }
      tree.delete_val(0, 0, max_t_len - 1, cur_t_idx);
      if (it != cur_t.end()) {
        long long next_t = *it;
        int idx = t_idx[next_t];
        long long next_val = tree.query_range(0, 0, max_t_len - 1, idx, idx);
        long long updated_val = prev_val + (next_t - prev_t) * prev_s;
        long long diff = updated_val - next_val;
        tree.bulk_add(0, 0, max_t_len - 1, idx, max_t_len - 1, diff);
      }
      cur_t.erase(t);
    } else {
      double res = -1;
      long long l, r, v;
      l = inp[i][1];
      r = inp[i][2];
      v = inp[i][3];
      set<long long>::iterator it = cur_t.lower_bound(l);
      if (v <= 0) {
        res = l;
      } else if (it != cur_t.end() && (*it) < r) {
        long long start_t = *it;
        int start_idx = t_idx[start_t];
        long long start_val =
            tree.query_range(0, 0, max_t_len - 1, start_idx, start_idx);
        long long target_val = start_val - v;
        set<long long>::iterator it2 = cur_t.upper_bound(r);
        it2--;
        long long end_t = *it2;
        long long end_s = t_s[end_t];
        int end_idx = t_idx[end_t];
        long long end_val =
            tree.query_range(0, 0, max_t_len - 1, end_idx, end_idx);
        int start = start_idx;
        int end = end_idx;
        long long foud_min = tree.max_res;
        while (start < end) {
          foud_min = tree.query_range(0, 0, max_t_len - 1, start, end);
          if (foud_min > target_val) {
            start = end;
            break;
          }
          int mid = (start + end) / 2;
          long long min_val = tree.query_range(0, 0, max_t_len - 1, start, mid);
          if (min_val > target_val) {
            start = mid + 1;
          } else {
            foud_min = min_val;
            end = mid;
          }
        }
        if (foud_min <= target_val) {
          long long t = idx_to_t[start];
          set<long long>::iterator it3 = cur_t.lower_bound(t);
          it3--;
          long long prev_t = *it3;
          long long prev_s = t_s[prev_t];
          int prev_idx = t_idx[prev_t];
          long long prev_val =
              tree.query_range(0, 0, max_t_len - 1, prev_idx, prev_idx);
          res = (double)prev_t +
                ((double)target_val - (double)prev_val) / (double)prev_s;
        } else {
          long long last_val = end_val + (r - end_t) * end_s;
          if (last_val <= target_val) {
            res = (double)end_t +
                  ((double)target_val - (double)end_val) / (double)end_s;
          }
        }
      }
      if (res < 0) {
        printf("%lf\n", res);
      } else {
        printf("%.10lf\n", res);
      }
    }
  }
  return 0;
}
