#include <bits/stdc++.h>

using namespace std;

#define int ll
typedef long long ll;
typedef long double ld;
typedef pair<int, int> pi;
typedef pair<ll, ll> pl;
typedef vector<int> vi;
typedef vector<ll> vl;
typedef vector<double> vd;
typedef vector<bool> vb;
typedef vector<char> vc;
typedef vector<string> vs;
typedef vector<pi> vp;
typedef vector<pl> vpl;



//preuzeto sa sajta:
//https://github.com/ivan100sic/competelib/blob/master/User/segtreelazy.sublime-snippet

template<int MAXN>
struct segtree_lazy {
    struct updater {
        /* DATA MEMBERS */
        int x;
        updater(int x = 0) : x(x) {}
        updater& operator+= (const updater& other) {
            /* ADDITION */
            x = other.x;
            return *this;
        }
        operator bool () const {
            /* BOOL CAST */
            return x != 0;
        }
    };
    
    struct node_t {
        /* DATA MEMBERS */
        int x;
        /* CONSTRUCTOR */
        node_t(int x = 0) : x(x) {}
        node_t& operator+= (const node_t& other) {
            /* ADDITION */
            x += other.x;
            return *this;
        }
        node_t& operator+= (const updater& other) {
            /* UPDATE ADDITION */
            x = other.x;
            return *this;
        }
        node_t operator+ (const node_t& other) const {
            node_t tmp = *this;
            tmp += other;
            return tmp;
        }
    };
    node_t a[2*MAXN];
    updater b[2*MAXN];
    void init() {
        for (int i=1; i<=MAXN; i++) {
            /* KOPIRAJ NEKI EKSTERNI NIZ OVDE */
            a[i + MAXN - 1] = node_t();
        }
        for (int i=MAXN-1; i>0; i--) {
            a[i] = a[2*i] + a[2*i+1];
        }
    }
    void push(int i) {
        if (b[i]) {
            a[i] += b[i];
            if (i < MAXN) {
                b[2*i] += b[i];
                b[2*i+1] += b[i];
            }
            b[i] = updater();
        }
    }
    node_t get(int l, int r, int node=1, int nl=1, int nr=MAXN) {
        push(node);
        if (r < nl || nr < l) {
            return node_t();
        }
        if (l <= nl && nr <= r) {
            return a[node];
        }
        int nm = (nl + nr) >> 1;
        return get(l, r, 2*node, nl, nm) + get(l, r, 2*node+1, nm+1, nr);
    }
    void update(int l, int r, updater val, int node=1, int nl=1, int nr=MAXN) {
        push(node);
        if (r < nl || nr < l) {
            return;
        }
        if (l <= nl && nr <= r) {
            b[node] += val;
            push(node);
            return;
        }
        int nm = (nl + nr) >> 1;
        update(l, r, val, 2*node, nl, nm);
        update(l, r, val, 2*node+1, nm+1, nr);
        a[node] = a[2*node] + a[2*node+1];
    }
};
segtree_lazy<2 * 131072> drvo;








int w, h, r, q;

//necu klasu nisam seljak
//ja sam dziber
struct krug{
    int x;
    int y;
};

ld sq(ld a){
    ld sol = a * a;
    return sol;
}

//dal je a bolji od b na m
bool f(krug a, krug b, ld m){
    ld ya = a.y - sqrt(sq(r) - sq(m - a.x));
    ld yb = b.y - sqrt(sq(r) - sq(m - b.x));

    ld h1 = 1.9 * h;
    ya = min(ya, h1);
    yb = min(yb, h1);

    if (ya <= yb)
        return 1;
    if (ya > yb)
        return 0;
}

ld g(krug a, ld m){
    ld y = a.y - sqrt(sq(r) - sq(m - a.x));

    ld h1 = 1.0 * h;
    y = min(y, h1);
    ld glupava_nula = 1.00000 * 0;
    y = max(y, glupava_nula);

    return y;
}

signed main()
{
    ios_base::sync_with_stdio(false); 
    cin.tie(nullptr); 
    cout.tie(nullptr); 
    cerr.tie(nullptr);    

    cin >> w >> h >> r >> q;

    vector<krug> a = {{-1,-1}};
    //marko inace nema ogranicenja, cista i neprebrojiva beskonacnost
    for (int marko = 0; marko < q; ++marko){
        int t;
        cin >> t;

        if (t == 1){
            int x, y;
            cin >> x >> y;

            a.push_back({x, y});

            int ind = a.size();
            --ind;

            //prvo proverim dal moze sredinu da dominira
            int k = drvo.get(x, x).x;
            bool ok = 0;
            if (!k || f(a[ind], a[k], x));{
                ok = 1;
            }

            if (!ok){
                continue;
            }

            int low = x, high = min(w, x + r - 1), r = x, l = x;
            while (low <= high){
                int mid = (low + high) / 2;

                k = drvo.get(mid, mid).x;
                if (!k || f(a[ind], a[k], mid)){
                    r = max(r, mid);
                    low = mid + 1;
                } else {
                    high = mid - 1;
                }
            }

            low = max(0ll, x - r + 1); high = x;
            while (low <= high){
                int mid = (low + high) / 2;

                k = drvo.get(mid, mid).x;
                if (!k || f(a[ind], a[k], mid)){
                    high = mid - 1;
                    l = min(l, mid);
                } else {
                    low = mid + 1;
                }
            }

            drvo.update(l, r, ind);
        } else {
            int x;
            cin >> x;

            int sol = drvo.get(x, x).x;

            ld res;
            if (sol)
                res = g(a[sol], x);
            else
                res = h * 1.00000;

            cout << fixed << setprecision(12) << res << '\n';
        }
    }
}