#include <bits/stdc++.h>
using namespace std;
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
const int MAXN = 100100;
const int inf = (int)1e9 + 1000;
const long long infll = (long long)1e18 + 1000;
int getRandom() { return uniform_int_distribution<int>(-inf, inf)(rng); }
struct Node {
  int time, speed, pr;
  int tL, tR, speedR;
  long long sum, minSum;
  int minPos;
  int l, r;
};
Node tree[MAXN];
int cnt = 1;
int getNode() { return cnt++; }
void update(int v) {
  if (!v) return;
  auto UPDATE_MIN = [&](long long val, int pos) -> void {
    if (val < tree[v].minSum) {
      tree[v].minPos = pos;
      tree[v].minSum = val;
    }
  };
  int l = tree[v].l, r = tree[v].r;
  tree[v].tL = tree[v].tR = tree[v].time;
  tree[v].speedR = tree[v].speed;
  tree[v].sum = 0;
  tree[v].minSum = 0;
  tree[v].minPos = tree[v].tL;
  long long gap1, gap2;
  if (l) {
    tree[v].tL = tree[l].tL;
    gap1 = (long long)(tree[v].time - tree[l].tR) * tree[l].speedR;
    tree[v].sum += tree[l].sum + gap1;
    UPDATE_MIN(tree[l].minSum, tree[l].minPos);
    UPDATE_MIN(tree[v].sum, tree[v].time);
  }
  if (r) {
    tree[v].tR = tree[r].tR;
    tree[v].speedR = tree[r].speedR;
    gap2 = (long long)(tree[r].tL - tree[v].time) * tree[v].speed;
    tree[v].sum += gap2 + tree[r].sum;
    if (!l) {
      UPDATE_MIN(gap2, tree[r].tL);
      UPDATE_MIN(gap2 + tree[r].minSum, tree[r].minPos);
    }
  }
  if (l && r) {
    UPDATE_MIN(tree[l].sum + gap1 + gap2 + tree[r].minSum, tree[r].minPos);
  }
  UPDATE_MIN(tree[v].sum, tree[v].tR);
}
void split(int t, int &L, int &R, int val) {
  if (!t) {
    L = R = 0;
  } else if (val >= tree[t].time) {
    split(tree[t].r, tree[t].r, R, val);
    L = t;
  } else {
    split(tree[t].l, L, tree[t].l, val);
    R = t;
  }
  update(t);
}
void merge(int &t, int l, int r) {
  if (!l || !r) {
    t = l ? l : r;
  } else if (tree[l].pr > tree[r].pr) {
    merge(tree[l].r, tree[l].r, r);
    t = l;
  } else {
    merge(tree[r].l, l, tree[r].l);
    t = r;
  }
  update(t);
}
void insert(int &t, int it) {
  if (!t) {
    t = it;
  } else if (tree[it].pr > tree[t].pr) {
    split(t, tree[it].l, tree[it].r, tree[it].time);
    t = it;
  } else {
    insert(tree[it].time >= tree[t].time ? tree[t].r : tree[t].l, it);
  }
  update(t);
}
void erase(int &t, int val) {
  if (!t)
    return;
  else if (tree[t].time == val) {
    merge(t, tree[t].l, tree[t].r);
  } else {
    erase(val > tree[t].time ? tree[t].r : tree[t].l, val);
  }
  update(t);
}
double query(int t, long long v) {
  if (tree[t].minSum + v > 0) return -1;
  int l = tree[t].l, r = tree[t].r;
  if (l) {
    if (v + tree[l].minSum <= 0) return query(l, v);
    long long gap1 = (long long)tree[l].speedR * (tree[t].time - tree[l].tR);
    if (v + tree[l].sum + gap1 <= 0)
      return (double)(v + tree[l].sum) / -tree[l].speedR + tree[l].tR;
    v += tree[l].sum + gap1;
  }
  if (r) {
    long long gap2 = (long long)tree[t].speed * (tree[r].tL - tree[t].time);
    if (v + gap2 <= 0) return (double)(v) / -tree[t].speed + tree[t].time;
    v += gap2;
    return query(r, v);
  }
  return -1;
}
double query(int &t, int a, int b, int v) {
  int l, r;
  if (v == 0) return a;
  split(t, l, r, a - 1);
  double ret;
  ret = query(r, v);
  merge(t, l, r);
  return ret - 1e-9 < b ? ret : -1;
}
int q;
void load() { scanf("%d", &q); }
void solve() {
  int t = 0;
  auto INSERT = [&](int time, int speed) -> void {
    int it = getNode();
    tree[it].time = time;
    tree[it].speed = speed;
    tree[it].pr = getRandom();
    insert(t, it);
  };
  INSERT(0, 0);
  INSERT(inf, 0);
  while (q--) {
    int a, b, c, d;
    scanf("%d", &a);
    if (a == 1) {
      scanf("%d%d", &b, &c);
      INSERT(b, c);
    } else if (a == 2) {
      scanf("%d", &b);
      erase(t, b);
    } else {
      scanf("%d%d%d", &b, &c, &d);
      printf("%.10lf\n", query(t, b, c, d));
    }
  }
}
int main() {
  load();
  solve();
  return 0;
}
