#include <bits/stdc++.h>
using namespace std;

typedef float rl;

#define pb push_back
#define mp make_pair
#define min3(a, b, c) min(min(a, b), c)
#define max3(a, b, c) max(max(a, b), c)

struct node
{
    rl A; // u[L]*u[L+1]*u[L+2]*...*u[R-1]*u[R]
    rl B; // u[L] + u[L]*u[L+1] + u[L]u[L+1]u[L+2] + ... + u[L]u[L+1]...u[R-1]u[R]
};

const node identity {.A = 1.0, .B=0.0};
inline node merge(node L, node R)
{
    return node
    {
        .A=L.A*R.A,
        .B= L.B + R.B*L.A
    };
}
inline node make(rl u)
{
    return node {.A=u, .B=u};
}

const int MX=100*1000+99;

struct seg_tree
{
    node V[4*MX];

    void build(int no, int L, int R, rl* U)
    {
        if(L>R)
        {
            V[no]=identity;
            return;
        }
        if(L==R)
        {
            V[no]=make(U[L]);
            return;
        }
        int M=(L+R)/2;

        build(no*2,   L,   M, U);
        build(no*2+1, M+1, R, U);
    }

    void upd(int no, int idx, int L, int R, rl u)
    {
        if(L>R) return;
        if(L==R)
        {
            V[no]=make(u);
            return;
        }
        int M=(L+R)/2;
        if(idx <= M) upd(no*2,   idx, L,   M, u);
        else         upd(no*2+1, idx, M+1, R, u);
    }

    node query(int no, int L, int R, int qL, int qR)
    {
        if(qL>qR) return identity;
        if(L==R) return V[no];

        int M=(L+R)/2;
        node left =query(2*no,   L,   M,            qL,  min(M, qR));
        node right=query(2*no+1, M+1, R,  max(M+1, qL),          qR);
        node ans=merge(left, right);

        return ans;
    }
};

seg_tree T;

int n, q;
rl U[MX];

int main()
{
	//freopen("input.txt", "r", stdin);
	//freopen("output.txt", "w", stdout);
    ios_base::sync_with_stdio(false);
    cin.tie(NULL); cout.tie(NULL);

    cin >> n >> q;

    for(int i=0; i<n; i++)
    {
        int a, b;
        cin >> a >> b;

        rl p=(a+0.0)/b;
        U[i]=(1.0-p)/p;
    }
    T.build(1, 0, n-1, U);

    cout << setprecision(6) << fixed;

    for(int t=0; t<q; t++)
    {
        int type;
        cin >> type;
        if(type==1)
        {
            int i, a, b;
            cin >> i >> a >> b;
            i--;

            rl p=(a+0.0)/b;
            rl u=(1.0-p)/p;

            T.upd(1, i, 0, n-1, u);
        }
        else
        {
            int l, r;
            cin >> l >> r;
            l--; r--;

            node ans=T.query(1, 0, n-1, l, r);
            rl res;
            if(ans.B<1E30)
            {
                //cout << 1.0/(1.0+ans.B) << '\n';
                res=1.0/(1.0+ans.B);
            }
            else
            {
                res=0.0;
            }
            cout << res << '\n';
        }
    }

	return 0;
}


#include <bits/stdc++.h>
using namespace std;

typedef float rl;

struct node
{
    rl A; // u[L]*u[L+1]*u[L+2]*...*u[R-1]*u[R]
    rl B; // u[L] + u[L]*u[L+1] + u[L]u[L+1]u[L+2] + ... + u[L]u[L+1]...u[R-1]u[R]
};

const node identity {.A = 1.0, .B=0.0};
inline node merge(node L, node R)
{
    return node
    {
        .A=L.A*R.A,
        .B= L.B + R.B*L.A
    };
}
inline node make(rl u)
{
    return node {.A=u, .B=u};
}

const int MX=100*1000+99;

struct seg_tree
{
    node V[4*MX];

    void build(int no, int L, int R, rl* U)
    {
        if(L>R)
        {
            V[no]=identity;
            return;
        }
        if(L==R)
        {
            V[no]=make(U[L]);
            return;
        }
        int M=(L+R)/2;

        build(no*2,   L,   M, U);
        build(no*2+1, M+1, R, U);
        V[no]=merge(V[2*no], V[2*no+1]);
    }

    void upd(int no, int idx, int L, int R, rl u)
    {
        if(L>R) return;
        if(L==R)
        {
            V[no]=make(u);
            return;
        }
        int M=(L+R)/2;
        if(idx <= M) upd(no*2,   idx, L,   M, u);
        else         upd(no*2+1, idx, M+1, R, u);
        V[no]=merge(V[2*no], V[2*no+1]);
    }

    node query(int no, int L, int R, int qL, int qR)
    {
        if(qL>qR) return identity;
        if(L==qL && qR==R) return V[no];

        int M=(L+R)/2;
        node left =query(2*no,   L,   M,            qL,  min(M, qR));
        node right=query(2*no+1, M+1, R,  max(M+1, qL),          qR);
        node ans=merge(left, right);

        return ans;
    }
};

seg_tree T;

int n, q;
rl U[MX];

int main()
{
    scanf("%d %d", &n, &q);

    for(int i=0; i<n; i++)
    {
        int a, b;
        cin >> a >> b;

        rl p=(a+0.0)/b;
        U[i]=(1.0-p)/p;
    }
    T.build(1, 0, n-1, U);

    for(int t=0; t<q; t++)
    {
        int type;
        cin >> type;
        if(type==1)
        {
            int i, a, b;
            scanf("%d %d %d", &i, &a, &b);
            i--;

            rl p=(a+0.0)/b;
            rl u=(1.0-p)/p;

            T.upd(1, i, 0, n-1, u);
        }
        else
        {
            int l, r;
            scanf("%d %d", &l, &r);
            l--; r--;

            node ans=T.query(1, 0, n-1, l, r);

            rl res;
            res=1.0/(1.0+ans.B);
            printf("%f\n", res);
        }
    }

	return 0;
}


#include <bits/stdc++.h>
using namespace std;

typedef unsigned int ui;
typedef unsigned long long ull;
typedef long long ll;
typedef pair<int, int> pii;
typedef long double rl;

#define pb push_back
#define mp make_pair
#define min3(a, b, c) min(min(a, b), c)
#define max3(a, b, c) max(max(a, b), c)

struct node
{
    rl A; // u[L]*u[L+1]*u[L+2]*...*u[R-1]*u[R]
    rl B; // u[L] + u[L]*u[L+1] + u[L]u[L+1]u[L+2] + ... + u[L]u[L+1]...u[R-1]u[R]
};

const node identity {.A = 1.0, .B=0.0};
inline node merge(node L, node R)
{
    return node
    {
        .A=L.A*R.A,
        .B= L.B + R.B*L.A
    };
}
inline node make(rl u)
{
    return node {.A=u, .B=u};
}

const int MX=100*1000+99;

struct seg_tree
{
    node V[4*MX];

    void build(int no, int L, int R, rl* U)
    {
        if(L>R)
        {
            V[no]=identity;
            return;
        }
        if(L==R)
        {
            V[no]=make(U[L]);
            return;
        }
        int M=(L+R)/2;

        build(no*2,   L,   M, U);
        build(no*2+1, M+1, R, U);
    }

    void upd(int no, int idx, int L, int R, rl u)
    {
        if(L>R) return;
        if(L==R)
        {
            V[no]=make(u);
            return;
        }
        int M=(L+R)/2;
        if(idx <= M) upd(no*2,   idx, L,   M, u);
        else         upd(no*2+1, idx, M+1, R, u);
    }

    node query(int no, int L, int R, int qL, int qR)
    {
        if(qL>qR) return identity;
        if(L==R) return V[no];

        int M=(L+R)/2;
        node left =query(2*no,   L,   M,            qL,  min(M, qR));
        node right=query(2*no+1, M+1, R,  max(M+1, qL),          qR);
        node ans=merge(left, right);

        return ans;
    }
};

seg_tree T;

int n, q;
rl U[MX];

int main()
{
	//freopen("input.txt", "r", stdin);
	//freopen("output.txt", "w", stdout);
    ios_base::sync_with_stdio(false);
    cin.tie(NULL); cout.tie(NULL);

    cin >> n >> q;

    for(int i=0; i<n; i++)
    {
        int a, b;
        cin >> a >> b;

        rl p=(a+0.0)/b;
        U[i]=(1.0-p)/p;
    }
    T.build(1, 0, n-1, U);

    cout << setprecision(6) << fixed;

    for(int t=0; t<q; t++)
    {
        int type;
        cin >> type;
        if(type==1)
        {
            int i, a, b;
            cin >> i >> a >> b;
            i--;

            rl p=(a+0.0)/b;
            rl u=(1.0-p)/p;

            T.upd(1, i, 0, n-1, u);
        }
        else
        {
            int l, r;
            cin >> l >> r;
            l--; r--;

            node ans=T.query(1, 0, n-1, l, r);
            if(ans.B<1E100)
            {
                cout << 1.0/(1.0+ans.B) << '\n';
            }
            else
            {
                cout << 0.0 << '\n';
            }
        }
    }

	return 0;
}


#include <bits/stdc++.h>
using namespace std;

typedef unsigned int ui;
typedef unsigned long long ull;
typedef long long ll;
typedef pair<int, int> pii;
typedef long double rl;

#define pb push_back
#define mp make_pair
#define min3(a, b, c) min(min(a, b), c)
#define max3(a, b, c) max(max(a, b), c)

struct node
{
    rl A; // u[L]*u[L+1]*u[L+2]*...*u[R-1]*u[R]
    rl B; // u[L] + u[L]*u[L+1] + u[L]u[L+1]u[L+2] + ... + u[L]u[L+1]...u[R-1]u[R]
};

const node identity {.A = 1.0, .B=0.0};
node merge(node L, node R)
{
    return node
    {
        .A=L.A*R.A,
        .B= L.B + R.B*L.A
    };
}
node make(rl u)
{
    return node {.A=u, .B=u};
}

const int MX=100*1000+99;

struct seg_tree
{
    vector<node> V;

    seg_tree()
    {
        V.resize(4*MX);
    }

    void build(int no, int L, int R, rl* U)
    {
        if(L>R)
        {
            V[no]=identity;
            return;
        }
        if(L==R)
        {
            V[no]=make(U[L]);
            return;
        }
        int M=(L+R)/2;

        build(no*2,   L,   M, U);
        build(no*2+1, M+1, R, U);
    }

    void upd(int no, int idx, int L, int R, rl u)
    {
        if(L>R) return;
        if(L==R)
        {
            V[no]=make(u);
            return;
        }
        int M=(L+R)/2;
        if(idx <= M) upd(no*2,   idx, L,   M, u);
        else         upd(no*2+1, idx, M+1, R, u);
    }

    /*
    node querypnt(int no, int idx, int L, int R)
    {
        if(L>R) return identity;
        if(L==R) return V[no];

        int M=(L+R)/2;
        if(idx<=M) return querypnt(no*2,   idx, L, M);
        else       return querypnt(no*2+1, idx, M+1, R);
    }
    */

    node query(int no, int L, int R, int qL, int qR)
    {
        // printf("%d %d %d %d %d\n", no, L, R, qL, qR);
        //assert(L<=qL && qR<=R);
        if(qL>qR) return identity;
        if(L==R) return V[no];

        int M=(L+R)/2;
        node left =query(2*no,   L,   M,            qL,  min(M, qR));
        node right=query(2*no+1, M+1, R,  max(M+1, qL),          qR);
        node ans=merge(left, right);

        //printf("%d %d %d %d %d:\n", no, L, R, qL, qR);
        //cout << ans.A << ' ' << ans.B << endl;

        return ans;
    }
};

seg_tree T;

int n, q;
rl U[MX];

int main()
{
	//freopen("input.txt", "r", stdin);
	//freopen("output.txt", "w", stdout);
    ios_base::sync_with_stdio(false);
    cin.tie(NULL); cout.tie(NULL);

    cin >> n >> q;

    for(int i=0; i<n; i++)
    {
        int a, b;
        cin >> a >> b;

        rl p=(a+0.0)/b;
        U[i]=(1.0-p)/p;
    }
    T.build(1, 0, n-1, U);

    cout << setprecision(6) << fixed;

    for(int t=0; t<q; t++)
    {
        int type;
        cin >> type;
        if(type==1)
        {
            int i, a, b;
            cin >> i >> a >> b;
            i--;

            rl p=(a+0.0)/b;
            rl u=(1.0-p)/p;

            T.upd(1, i, 0, n-1, u);
        }
        else
        {
            int l, r;
            cin >> l >> r;
            l--; r--;

            node ans=T.query(1, 0, n-1, l, r);
            if(ans.B<1E100)
            {
                cout << 1.0/(1.0+ans.B) << '\n';
            }
            else
            {
                cout << 0.0 << '\n';
            }
        }
    }

	return 0;
}


#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#define ll long long
#define db long double
#define N 100010
#define eps 1e-8
#define max(a, b) ((a) > (b) ? (a) : (b))
#define min(a, b) ((a) < (b) ? (a) : (b))
#define swap(T, a, b) ({T ttt = a; a = b; b = ttt;})
int n, a, b, T, t;
db p[N], g[N], u[N], Ans, tA, tB;
#define a f
struct Node { int l, r; db v, Sum; } a[N*5];
void Tag(int k, db x)
{
   if (a[k].v > eps) a[k].v *= x;
   else a[k].v = x;
   a[k].Sum *= x;
}
void pushdown(int k)
{
   db t = a[k].v;
   if (a[k].l != a[k].r)
   {
      Tag(k<<1, t);
      Tag((k<<1)+1, t);
   }
   a[k].v = 0;
}
void Build(int k, int l, int r)
{
   a[k].l = l; a[k].r = r; a[k].v = 0;
   if (l == r) { a[k].Sum = g[l]; return; }
   int mid = (l + r) >> 1;
   Build(k<<1, l, mid); Build((k<<1)+1, mid+1, r);
   a[k].Sum = a[k<<1].Sum + a[(k<<1)+1].Sum;
}
db Ask(int k, int l, int r)
{
   if (a[k].l == l && a[k].r == r) return a[k].Sum;
   if (a[k].v > eps) pushdown(k);
   int mid = (a[k].l + a[k].r) >> 1;
   db s;
   if (r <= mid) s = Ask(k<<1, l, r);
   else if (l > mid) s = Ask((k<<1)+1, l, r);
   else s = Ask(k<<1, l, mid) + Ask((k<<1)+1, mid + 1, r);
   a[k].Sum = a[k<<1].Sum + a[(k<<1)+1].Sum;
   return s;
}
void Update(int k, int l, int r, db x)
{
   if (a[k].l == l && a[k].r == r)
   {
      Tag(k, x);
      return;
   }
   int mid = (a[k].l + a[k].r) >> 1;
   if (a[k].v > 0) pushdown(k);
   if (r <= mid) Update(k<<1, l, r, x);
   else if (l > mid) Update((k<<1)+1, l, r, x);
   else
   {
      Update(k<<1, l, mid, x);
      Update((k<<1)+1, mid+1, r, x);
   }
   a[k].Sum = a[k<<1].Sum + a[(k<<1)+1].Sum;
}
#undef a
int main()
{
   scanf("%d%d", &n, &T);
   for (int i = 1; i <= n; i++)
   {
      scanf("%d%d", &a, &b);
      p[i] = (db)a / b;
      u[i] = 1 / p[i] - 1;
   }
   g[0] = 1;
   for (int i = 1; i <= n; i++)
      g[i] = g[i - 1] * u[i];
   Build(1, 1, n);
   while (T--)
   {
      scanf("%d", &t);
      if (t == 1)
      {
	 scanf("%d%d%d", &t, &a, &b);
	 Update(1, t, n, ((db)b / a - 1) / u[t]);
	 u[t] = (db)b / a - 1;
      }
      else
      {
	 scanf("%d%d", &a, &b);
	 if (a == 1) Ans = 1.0 / (Ask(1, a, b) + 1);
	 else
	 {
	    tA = Ask(1, a-1, a-1); tB = Ask(1, a, b);
	    if (tA / tB > 1e7) Ans = 0;
	    else Ans = 1.0 / (1.0 + tB / tA);
	 }
	 printf("%.10f\n", (double)Ans);
      }
   }
   return 0;
}


#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#define ll long long
#define db double
#define N 100010
#define max(a, b) ((a) > (b) ? (a) : (b))
#define min(a, b) ((a) < (b) ? (a) : (b))
#define swap(T, a, b) ({T ttt = a; a = b; b = ttt;})
int n, a, b, T, t;
db p[N], g[N], u[N], Ans;
#define a f
#define Tag(k, x) {if (a[(k)].v != 0) a[(k)].v *= x; else a[(k)].v = x;}
struct Node { int l, r; db v, Sum; } a[N*5];
void pushdown(int k)
{
   db t = a[k].v; a[k].Sum *= t;
   Tag(k<<1, t) Tag((k<<1)+1, t)
   a[k].v = 0;
}
void Build(int k, int l, int r)
{
   a[k].l = l; a[k].r = r; a[k].v = 0;
   if (l == r) { a[k].Sum = g[l]; return; }
   int mid = (l + r) >> 1;
   Build(k<<1, l, mid); Build((k<<1)+1, mid+1, r);
   a[k].Sum = a[k<<1].Sum + a[(k<<1)+1].Sum;
}
db Ask(int k, int l, int r)
{
   if (a[k].l == l && a[k].r == r) return a[k].Sum;
   if (a[k].v) pushdown(k);
   int mid = (a[k].l + a[k].r) >> 1;
   if (r <= mid) return Ask(k<<1, l, r);
   else if (l > mid) return Ask((k<<1) + 1, l, r);
   else return Ask(k<<1, l, mid) + Ask((k<<1)+1, mid + 1, r);
}
void Update(int k, int l, int r, db x)
{
   if (a[k].l == l && a[k].r == r)
   {
      Tag(k, x);
      pushdown(k);
      return;
   }
   int mid = (a[k].l + a[k].r) >> 1;
   if (a[k].v) pushdown(k);
   if (r <= mid) Update(k<<1, l, r, x);
   else if (l > mid) Update((k<<1)+1, l, r, x);
   else
   {
      Update(k<<1, l, mid, x);
      Update((k<<1)+1, mid+1, r, x);
   }
   a[k].Sum = a[k<<1].Sum + a[(k<<1)+1].Sum;
}
#undef a
int main()
{
   scanf("%d%d", &n, &T);
   for (int i = 1; i <= n; i++)
   {
      scanf("%d%d", &a, &b);
      p[i] = (db)a / b;
      u[i] = 1 / p[i] - 1;
   }
   g[0] = 1;
   for (int i = 1; i <= n; i++)
      g[i] = g[i - 1] * u[i];
   Build(1, 1, n);
   while (T--)
   {
      scanf("%d", &t);
      if (t == 1)
      {
	 scanf("%d%d%d", &t, &a, &b);
	 Update(1, t, n, ((db)b / a - 1) / u[t]);
	 u[t] = (db)b / a - 1;
      }
      else
      {
	 scanf("%d%d", &a, &b);
	 if (a == 1) Ans = 1.0 / (Ask(1, a, b) + 1);
	 else
	 {
	    Ans = Ask(1, a-1, a-1);
	    Ans = Ans / (Ans + Ask(1, a, b));
	 }
	 printf("%.10f\n", Ans);
      }
   }
   return 0;
}


#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#define ll long long
#define db long double
#define N 100010
#define eps 1e-8
#define max(a, b) ((a) > (b) ? (a) : (b))
#define min(a, b) ((a) < (b) ? (a) : (b))
#define swap(T, a, b) ({T ttt = a; a = b; b = ttt;})
int n, a, b, T, t;
db p[N], g[N], u[N], Ans, tA, tB;
#define a f
struct Node { int l, r; db v, Sum; } a[N*5];
void Tag(int k, db x)
{
   if (a[k].v > eps) a[k].v *= x;
   else a[k].v = x;
   a[k].Sum *= x;
}
void pushdown(int k)
{
   db t = a[k].v;
   if (a[k].l != a[k].r)
   {
      Tag(k<<1, t);
      Tag((k<<1)+1, t);
   }
   a[k].v = 0;
}
void Build(int k, int l, int r)
{
   a[k].l = l; a[k].r = r; a[k].v = 0;
   if (l == r) { a[k].Sum = g[l]; return; }
   int mid = (l + r) >> 1;
   Build(k<<1, l, mid); Build((k<<1)+1, mid+1, r);
   a[k].Sum = a[k<<1].Sum + a[(k<<1)+1].Sum;
}
db Ask(int k, int l, int r)
{
   if (a[k].l == l && a[k].r == r) return a[k].Sum;
   if (a[k].v > eps) pushdown(k);
   int mid = (a[k].l + a[k].r) >> 1;
   db s;
   if (r <= mid) s = Ask(k<<1, l, r);
   else if (l > mid) s = Ask((k<<1)+1, l, r);
   else s = Ask(k<<1, l, mid) + Ask((k<<1)+1, mid + 1, r);
   a[k].Sum = a[k<<1].Sum + a[(k<<1)+1].Sum;
   return s;
}
void Update(int k, int l, int r, db x)
{
   if (a[k].l == l && a[k].r == r)
   {
      Tag(k, x);
      return;
   }
   int mid = (a[k].l + a[k].r) >> 1;
   if (a[k].v > 0) pushdown(k);
   if (r <= mid) Update(k<<1, l, r, x);
   else if (l > mid) Update((k<<1)+1, l, r, x);
   else
   {
      Update(k<<1, l, mid, x);
      Update((k<<1)+1, mid+1, r, x);
   }
   a[k].Sum = a[k<<1].Sum + a[(k<<1)+1].Sum;
}
#undef a
int main()
{
   scanf("%d%d", &n, &T);
   for (int i = 1; i <= n; i++)
   {
      scanf("%d%d", &a, &b);
      p[i] = (db)a / b;
      u[i] = 1 / p[i] - 1;
   }
   g[0] = 1;
   for (int i = 1; i <= n; i++)
      g[i] = g[i - 1] * u[i];
   Build(1, 1, n);
   while (T--)
   {
      scanf("%d", &t);
      if (t == 1)
      {
	 scanf("%d%d%d", &t, &a, &b);
	 Update(1, t, n, ((db)b / a - 1) / u[t]);
	 u[t] = (db)b / a - 1;
      }
      else
      {
	 scanf("%d%d", &a, &b);
	 if (a == 1) Ans = 1.0 / (Ask(1, a, b) + 1);
	 else
	 {
	    tA = Ask(1, a-1, a-1); tB = Ask(1, a, b);
	    if (tA > tB * 100000) Ans = 0;
	    else Ans = tA / (tA + tB);
	 }
	 printf("%.10f\n", (double)Ans);
      }
   }
   return 0;
}


#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#define ll long long
#define db double
#define N 100010
#define eps 1e-8
#define max(a, b) ((a) > (b) ? (a) : (b))
#define min(a, b) ((a) < (b) ? (a) : (b))
#define swap(T, a, b) ({T ttt = a; a = b; b = ttt;})
int n, a, b, T, t;
db p[N], g[N], u[N], Ans;
#define a f
struct Node { int l, r; db v, Sum; } a[N*5];
void Tag(int k, db x)
{
   if (a[k].v > eps) a[k].v *= x;
   else a[k].v = x;
   a[k].Sum *= x;
}
void pushdown(int k)
{
   db t = a[k].v;
   if (a[k].l != a[k].r)
   {
      Tag(k<<1, t);
      Tag((k<<1)+1, t);
   }
   a[k].v = 0;
}
void Build(int k, int l, int r)
{
   a[k].l = l; a[k].r = r; a[k].v = 0;
   if (l == r) { a[k].Sum = g[l]; return; }
   int mid = (l + r) >> 1;
   Build(k<<1, l, mid); Build((k<<1)+1, mid+1, r);
   a[k].Sum = a[k<<1].Sum + a[(k<<1)+1].Sum;
}
db Ask(int k, int l, int r)
{
   if (a[k].l == l && a[k].r == r) return a[k].Sum;
   if (a[k].v > eps) pushdown(k);
   int mid = (a[k].l + a[k].r) >> 1;
   db s;
   if (r <= mid) s = Ask(k<<1, l, r);
   else if (l > mid) s = Ask((k<<1)+1, l, r);
   else s = Ask(k<<1, l, mid) + Ask((k<<1)+1, mid + 1, r);
   a[k].Sum = a[k<<1].Sum + a[(k<<1)+1].Sum;
   return s;
}
void Update(int k, int l, int r, db x)
{
   if (a[k].l == l && a[k].r == r)
   {
      Tag(k, x);
      return;
   }
   int mid = (a[k].l + a[k].r) >> 1;
   if (a[k].v > 0) pushdown(k);
   if (r <= mid) Update(k<<1, l, r, x);
   else if (l > mid) Update((k<<1)+1, l, r, x);
   else
   {
      Update(k<<1, l, mid, x);
      Update((k<<1)+1, mid+1, r, x);
   }
   a[k].Sum = a[k<<1].Sum + a[(k<<1)+1].Sum;
}
#undef a
int main()
{
   scanf("%d%d", &n, &T);
   for (int i = 1; i <= n; i++)
   {
      scanf("%d%d", &a, &b);
      p[i] = (db)a / b;
      u[i] = 1 / p[i] - 1;
   }
   g[0] = 1;
   for (int i = 1; i <= n; i++)
      g[i] = g[i - 1] * u[i];
   Build(1, 1, n);
   while (T--)
   {
      scanf("%d", &t);
      if (t == 1)
      {
	 scanf("%d%d%d", &t, &a, &b);
	 Update(1, t, n, ((db)b / a - 1) / u[t]);
	 u[t] = (db)b / a - 1;
      }
      else
      {
	 scanf("%d%d", &a, &b);
	 if (a == 1) Ans = 1.0 / (Ask(1, a, b) + 1);
	 else
	 {
	    Ans = Ask(1, a-1, a-1);
	    Ans = Ans / (Ans + Ask(1, a, b));
	 }
	 printf("%.10f\n", (double)Ans);
      }
   }
   return 0;
}


#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#define ll long long
#define db long double
#define N 100010
#define eps 1e-8
#define max(a, b) ((a) > (b) ? (a) : (b))
#define min(a, b) ((a) < (b) ? (a) : (b))
#define swap(T, a, b) ({T ttt = a; a = b; b = ttt;})
int n, a, b, T, t;
db p[N], g[N], u[N], Ans, tA, tB;
#define a f
struct Node { int l, r; db tA, tB; } a[N*5];
void pushup(int k)
{
   a[k].tA = a[k<<1].tA * a[(k<<1)+1].tA;
   a[k].tB = a[k<<1].tB + a[(k<<1)+1].tB * a[k<<1].tA;
}
void Build(int k, int l, int r)
{
   a[k].l = l; a[k].r = r;
   if (l == r) { a[k].tA = a[k].tB = u[l]; return; }
   int mid = (l + r) >> 1;
   Build(k<<1, l, mid); Build((k<<1)+1, mid+1, r);
   pushup(k);
}
db AM(int k, int l, int r)
{
   if (a[k].l == l && a[k].r == r) return a[k].tA;
   int mid = (a[k].l + a[k].r) >> 1;
   if (r <= mid) return AM(k<<1, l, r);
   else if (l > mid) return AM((k<<1)+1, l, r);
   else return AM(k<<1, l, mid) * AM((k<<1)+1, mid + 1, r);
}
db Ask(int k, int l, int r)
{
   if (a[k].l == l && a[k].r == r) return a[k].tB;
   int mid = (a[k].l + a[k].r) >> 1;
   if (r <= mid) return Ask(k<<1, l, r);
   else if (l > mid) return Ask((k<<1)+1, l, r);
   else return Ask(k<<1, l, mid) + AM(k<<1, l, mid) * Ask((k<<1)+1, mid + 1, r);
}
void Update(int k, int t)
{
   if (a[k].l == a[k].r)
   {
      a[k].tA = a[k].tB = u[t];
      return;
   }
   int mid = (a[k].l + a[k].r) >> 1;
   if (t <= mid) Update(k<<1, t);
   else Update((k<<1)+1, t);
   pushup(k);
}
#undef a
int main()
{
   scanf("%d%d", &n, &T);
   for (int i = 1; i <= n; i++)
   {
      scanf("%d%d", &a, &b);
      p[i] = (db)a / b;
      u[i] = 1 / p[i] - 1;
   }
   g[0] = 1;
   for (int i = 1; i <= n; i++)
      g[i] = g[i - 1] * u[i];
   Build(1, 1, n);
   while (T--)
   {
      scanf("%d", &t);
      if (t == 1)
      {
	 scanf("%d%d%d", &t, &a, &b);
	 u[t] = (db)b / a - 1;
	 Update(1, t);
      }
      else
      {
	 scanf("%d%d", &a, &b);
	 if (a == 1) Ans = 1.0 / (Ask(1, a, b) + 1);
	 else
	 {
	    tA = Ask(1, a-1, a-1); tB = Ask(1, a, b);
	    if (tA / tB > 1e7) Ans = 0;
	    else Ans = 1.0 / (1.0 + tB / tA);
	    Ans = 1.0 / (1.0 + Ask(1, a, b));
	 }
	 printf("%.10f\n", (double)Ans);
      }
   }
   return 0;
}


#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#define ll long long
#define db long double
#define N 100010
#define eps 1e-8
#define max(a, b) ((a) > (b) ? (a) : (b))
#define min(a, b) ((a) < (b) ? (a) : (b))
#define swap(T, a, b) ({T ttt = a; a = b; b = ttt;})
int n, a, b, T, t;
db p[N], g[N], u[N], Ans;
#define a f
struct Node { int l, r; db v, Sum; } a[N*5];
void Tag(int k, db x)
{
   if (a[k].v > eps) a[k].v *= x;
   else a[k].v = x;
   a[k].Sum *= x;
}
void pushdown(int k)
{
   db t = a[k].v;
   if (a[k].l != a[k].r)
   {
      Tag(k<<1, t);
      Tag((k<<1)+1, t);
   }
   a[k].v = 0;
}
void Build(int k, int l, int r)
{
   a[k].l = l; a[k].r = r; a[k].v = 0;
   if (l == r) { a[k].Sum = g[l]; return; }
   int mid = (l + r) >> 1;
   Build(k<<1, l, mid); Build((k<<1)+1, mid+1, r);
   a[k].Sum = a[k<<1].Sum + a[(k<<1)+1].Sum;
}
db Ask(int k, int l, int r)
{
   if (a[k].l == l && a[k].r == r) return a[k].Sum;
   if (a[k].v > eps) pushdown(k);
   int mid = (a[k].l + a[k].r) >> 1;
   db s;
   if (r <= mid) s = Ask(k<<1, l, r);
   else if (l > mid) s = Ask((k<<1)+1, l, r);
   else s = Ask(k<<1, l, mid) + Ask((k<<1)+1, mid + 1, r);
   a[k].Sum = a[k<<1].Sum + a[(k<<1)+1].Sum;
   return s;
}
void Update(int k, int l, int r, db x)
{
   if (a[k].l == l && a[k].r == r)
   {
      Tag(k, x);
      return;
   }
   int mid = (a[k].l + a[k].r) >> 1;
   if (a[k].v > 0) pushdown(k);
   if (r <= mid) Update(k<<1, l, r, x);
   else if (l > mid) Update((k<<1)+1, l, r, x);
   else
   {
      Update(k<<1, l, mid, x);
      Update((k<<1)+1, mid+1, r, x);
   }
   a[k].Sum = a[k<<1].Sum + a[(k<<1)+1].Sum;
}
#undef a
int main()
{
   scanf("%d%d", &n, &T);
   for (int i = 1; i <= n; i++)
   {
      scanf("%d%d", &a, &b);
      p[i] = (db)a / b;
      u[i] = 1 / p[i] - 1;
   }
   g[0] = 1;
   for (int i = 1; i <= n; i++)
      g[i] = g[i - 1] * u[i];
   Build(1, 1, n);
   while (T--)
   {
      scanf("%d", &t);
      if (t == 1)
      {
	 scanf("%d%d%d", &t, &a, &b);
	 Update(1, t, n, ((db)b / a - 1) / u[t]);
	 u[t] = (db)b / a - 1;
      }
      else
      {
	 scanf("%d%d", &a, &b);
	 if (a == 1) Ans = 1.0 / (Ask(1, a, b) + 1);
	 else
	 {
	    Ans = Ask(1, a-1, a-1);
	    Ans = Ans / (Ans + Ask(1, a, b));
	 }
	 printf("%.10f\n", (double)Ans);
      }
   }
   return 0;
}


//TLE算法。。估计只要改成线段树就能AC了。。
%:pragma GCC optimize(3)
#include<cstdio>
#include<iostream>
#define xxx 100100
using namespace std;
double t[xxx],p[xxx],t1,t2,s[xxx],ans;
int n,q,type,l,r,x;

int main()
{
	scanf("%d%d",&n,&q);
	s[0]=1;
	for (int i=1;i<=n;i++)
	{
		scanf("%lf%lf",&t1,&t2);
		p[i]=t1/t2;
		t[i]=(1-p[i])/p[i];
		s[i]=s[i-1]*t[i];
	}
	while (q--)
	{
		scanf("%d",&type);
		if (type==1)
		{
			scanf("%d%lf%lf",&x,&t1,&t2);
			p[x]=t1/t2;
			t[x]=(1-p[x])/p[x];
			s[0]=1;
			for (int i=1;i<=n;i++)
				s[i]=s[i-1]*t[i];
		}
		else
		{
			scanf("%d%d",&l,&r);
			ans=s[l-1];
			for (int i=l;i<=r;i++)
				ans+=s[i];
			if (ans>1e15||ans==0) ans=0;
			else ans=s[l-1]/ans;
			printf("%.10lf\n",ans);
		}
	}
}


//TLE算法。。估计只要改成线段树就能AC了。。
%:pragma GCC optimize(3)
#include<cstdio>
#include<iostream>
#define xxx 100100
using namespace std;
double t[xxx],p[xxx],t1,t2,s[xxx],ans;
int n,q,type,l,r,x;

int main()
{
	scanf("%d%d",&n,&q);
	s[0]=1;
	for (int i=1;i<=n;i++)
	{
		scanf("%lf%lf",&t1,&t2);
		p[i]=t1/t2;
		t[i]=(1-p[i])/p[i];
		s[i]=s[i-1]*t[i];
	}
	while (q--)
	{
		scanf("%d",&type);
		if (type==1)
		{
			scanf("%d%lf%lf",&x,&t1,&t2);
			p[x]=t1/t2;
			t[x]=(1-p[x])/p[x];
			s[0]=1;
			for (int i=1;i<=n;i++)
				s[i]=s[i-1]*t[i];
		}
		else
		{
			scanf("%d%d",&l,&r);
			ans=s[l-1];
			for (int i=l;i<=r;i++)
				ans+=s[i];
			printf("%.10lf\n",s[l-1]/ans);
		}
	}
}


#include<cstdio>
#include<iostream>
#include<cmath>
#define mid ((l+r)>>1)
using namespace std;
double t[100100],t1,t2;
int n,q,type,st,en,w;
struct line_tree{
	double sum_up,single;
}tr[2332333],nil;
line_tree together(line_tree tr1,line_tree tr2){
	return (line_tree){tr1.sum_up+tr1.single*tr2.sum_up,tr1.single*tr2.single};
}
line_tree build(int x,int l,int r){
	if (l==r) return tr[x]=(line_tree){t[l],t[l]};
	return tr[x]=together(build(x<<1,l,mid),build(x<<1|1,mid+1,r));
}
line_tree change(int x,int l,int r,int p){
	if (l>p||r<p) return tr[x];
	if (l==r) return tr[x]=(line_tree){t[l],t[l]};
	return tr[x]=together(change(x<<1,l,mid,p),change(x<<1|1,mid+1,r,p));
}
line_tree que(int x,int l,int r,int st,int en){
	if (l==st&&r==en) return tr[x];
	if (en<=mid) return que(x<<1,l,mid,st,en);
	if (st> mid) return que(x<<1|1,mid+1,r,st,en);
	return together(que(x<<1,l,mid,st,mid),que(x<<1|1,mid+1,r,mid+1,en));
}
int main()
{
	nil.single=1;nil.sum_up=0;
	scanf("%d%d",&n,&q);
	for (int i=1;i<=n;i++){
		cin>>t1>>t2;
		t[i]=(1.0-(t1/t2))/(t1/t2);
	}
	build(1,1,n);
	while (q--){
		cin>>type;
		if (type==1){
			cin>>w>>t1>>t2;
			t[w]=(1.0-(t1/t2))/(t1/t2);
			change(1,1,n,w);
		}
		else{
			cin>>st>>en;
			t1=que(1,1,n,st,en).sum_up;
			printf("%.10lf\n",t1>1e15?0:1.0/(t1+1));
		}
	}
}


//TLE算法。。估计只要改成线段树就能AC了。。
%:pragma GCC optimize(3)
#include<cstdio>
#include<iostream>
#include<cmath>
#define xxx 100100
#define eps 0.000000001
using namespace std;
double t[xxx],p[xxx],t1,t2,s[xxx],ans;
int n,q,type,l,r,x;

int main()
{
	scanf("%d%d",&n,&q);
	s[0]=1;
	for (int i=1;i<=n;i++)
	{
		scanf("%lf%lf",&t1,&t2);
		p[i]=t1/t2; //if (abs(p[i])<=eps) while (1);
		t[i]=(1-p[i])/p[i];
		s[i]=s[i-1]*t[i];
	}
	while (q--)
	{
		scanf("%d",&type);
		if (type==1)
		{
			scanf("%d%lf%lf",&x,&t1,&t2);
			p[x]=t1/t2; //if (abs(p[x])<=eps) while (1);
			t[x]=(1-p[x])/p[x];
			s[0]=1;
			for (int i=1;i<=n;i++)
				s[i]=s[i-1]*t[i];
		}
		else
		{
			scanf("%d%d",&l,&r);
			ans=1;
			for (int i=l;i<=r;i++)
				ans+=s[i]/s[l-1];
			if (ans<=eps) while(1);
			if (ans>1e15) ans=0;
			else ans=1/ans;
			printf("%.10lf\n",ans);
		}
	}
}


//TLE算法。。估计只要改成线段树就能AC了。。
%:pragma GCC optimize(3)
#include<cstdio>
#include<iostream>
#define xxx 100100
using namespace std;
double t[xxx],p[xxx],t1,t2,s[xxx],ans;
int n,q,type,l,r,x;

int main()
{
	scanf("%d%d",&n,&q);
	s[0]=1;
	for (int i=1;i<=n;i++)
	{
		scanf("%lf%lf",&t1,&t2);
		p[i]=t1/t2;
		t[i]=(1-p[i])/p[i];
		s[i]=s[i-1]*t[i];
	}
	while (q--)
	{
		scanf("%d",&type);
		if (type==1)
		{
			scanf("%d%lf%lf",&x,&t1,&t2);
			p[x]=t1/t2;
			t[x]=(1-p[x])/p[x];
			s[0]=1;
			for (int i=1;i<=n;i++)
				s[i]=s[i-1]*t[i];
		}
		else
		{
			scanf("%d%d",&l,&r);
			ans=s[l-1];
			for (int i=l;i<=r;i++)
				ans+=s[i];
			ans=s[l-1]/ans;
			printf("%.10lf\n",ans);
		}
	}
}


//TLE算法。。估计只要改成线段树就能AC了。。
#include<cstdio>
#include<iostream>
#include<cmath>
#define xxx 100100
using namespace std;
double t[xxx],p[xxx],t1,t2,s[xxx],ans;
int n,q,type,l,r,x;

int main()
{
	scanf("%d%d",&n,&q);
	s[0]=1;
	for (int i=1;i<=n;i++)
	{
		scanf("%lf%lf",&t1,&t2);
		p[i]=t1/t2;
		t[i]=((double)1-p[i])/p[i];
		s[i]=s[i-1]*t[i];
		if (s[i]>1e300) while(1);
	}
	while (q--)
	{
		scanf("%d",&type);
		if (type==1)
		{
			scanf("%d%lf%lf",&x,&t1,&t2);
			p[x]=t1/t2;
			t[x]=((double)1-p[x])/p[x];
			s[0]=1;
			for (int i=1;i<=n;i++)
			{
				s[i]=s[i-1]*t[i];
				if (s[i]>1e300) while(1);
			}

		}
		else
		{
			scanf("%d%d",&l,&r);
			ans=1;
			for (int i=l;i<=r;i++)
				ans+=s[i]/s[l-1];
			if (ans>1e15) ans=0;
			else ans=(double)1/ans;
			printf("%.10lf\n",ans);
		}
	}
}


//TLE算法。。估计只要改成线段树就能AC了。。
%:pragma GCC optimize(3)
#include<cstdio>
#include<iostream>
#define xxx 100100
using namespace std;
double t[xxx],p[xxx],t1,t2,s[xxx],ans,tem;
int n,q,type,l,r,x;

int main()
{
	scanf("%d%d",&n,&q);
	s[0]=1;
	for (int i=1;i<=n;i++)
	{
		scanf("%lf%lf",&t1,&t2);
		p[i]=t1/t2;
		t[i]=(1-p[i])/p[i];
		s[i]=s[i-1]*t[i];
	}
	while (q--)
	{
		scanf("%d",&type);
		if (type==1)
		{
			scanf("%d%lf%lf",&x,&t1,&t2);
			p[x]=t1/t2;
			t[x]=(1-p[x])/p[x];
			for (int i=x;i<=n;i++)
				s[i]=s[i-1]*t[i];
		}
		else
		{
			scanf("%d%d",&l,&r);
			ans=1;
			for (int i=l;i<=r;i++)
				ans+=s[i]/s[l-1];
			printf("%.10lf\n",1/ans);
		}
	}
}


//TLE算法。。估计只要改成线段树就能AC了。。
%:pragma GCC optimize(3)
#include<cstdio>
#include<iostream>
#include<cmath>
#define xxx 100100
#define eps 0.00000000001
using namespace std;
double t[xxx],p[xxx],t1,t2,s[xxx],ans;
int n,q,type,l,r,x;

int main()
{
	scanf("%d%d",&n,&q);
	s[0]=1;
	for (int i=1;i<=n;i++)
	{
		scanf("%lf%lf",&t1,&t2);
		p[i]=t1/t2;
		t[i]=((double)1-p[i])/p[i];
		s[i]=s[i-1]*t[i];
	}
	while (q--)
	{
		scanf("%d",&type);
		if (type==1)
		{
			scanf("%d%lf%lf",&x,&t1,&t2);
			p[x]=t1/t2;
			t[x]=((double)1-p[x])/p[x];
			s[0]=1;
			for (int i=1;i<=n;i++)
				s[i]=s[i-1]*t[i];
		}
		else
		{
			scanf("%d%d",&l,&r);
			ans=1;
			for (int i=l;i<=r;i++)
				ans+=s[i]/s[l-1];
			if (ans>1e15) ans=0;
			else ans=(double)1/ans;
			printf("%.10lf\n",ans);
		}
	}
}


//TLE算法。。估计只要改成线段树就能AC了。。
%:pragma GCC optimize(3)
#include<cstdio>
#include<iostream>
#include<cmath>
#define xxx 100100
#define eps 0.000000001
using namespace std;
double t[xxx],p[xxx],t1,t2,s[xxx],ans;
int n,q,type,l,r,x;

int main()
{
	scanf("%d%d",&n,&q);
	s[0]=1;
	for (int i=1;i<=n;i++)
	{
		scanf("%lf%lf",&t1,&t2);
		p[i]=t1/t2; if (abs(p[i])<=eps) while (1);
		t[i]=(1-p[i])/p[i];
		s[i]=s[i-1]*t[i];
	}
	while (q--)
	{
		scanf("%d",&type);
		if (type==1)
		{
			scanf("%d%lf%lf",&x,&t1,&t2);
			p[x]=t1/t2; if (abs(p[x])<=eps) while (1);
			t[x]=(1-p[x])/p[x];
			s[0]=1;
			for (int i=1;i<=n;i++)
				s[i]=s[i-1]*t[i];
		}
		else
		{
			scanf("%d%d",&l,&r);
			ans=1;
			for (int i=l;i<=r;i++)
				ans+=s[i]/s[l-1];
			if (s[l-1]<eps) while(1);
			if (ans>1e15||ans==0) ans=0;
			else ans=1/ans;
			printf("%.10lf\n",ans);
		}
	}
}


#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fd(i,a,b) for(int i=a;i>=b;i--)
#define maxn 100005
#define db double
using namespace std;

struct seg{
    db a,b;
}t[maxn * 4],now;

int n,q;

db p[maxn];

void build(int v,int l,int r){
    if (l==r) {
        t[v].a=t[v].b=(1-p[l])/p[l];
        return;
    }
    int mid=(l+r) >> 1;
    build(v << 1,l,mid);
    build(v << 1 | 1,mid+1,r);
    t[v].a=t[v << 1].a*t[v << 1 | 1].a; if (t[v].a>1e300) while(1);
    t[v].b=t[v << 1].b+t[v << 1 | 1].b*t[v << 1].a;
}

void change(int v,int l,int r,int x){
    if (l==r) {
        t[v].a=t[v].b=(1-p[l])/p[l];
        return;
    }
    int mid=(l+r) >> 1;
    if (x<=mid) change(v << 1,l,mid,x);
    else change(v << 1 | 1,mid+1,r,x);
    t[v].a=t[v << 1].a*t[v << 1 | 1].a;
    t[v].b=t[v << 1].b+t[v << 1 | 1].b*t[v << 1].a;
}

void query(int v,int l,int r,int x,int y){
    if (l==x && r==y) {
        now.b=now.b+now.a*t[v].b;
        now.a=now.a*t[v].a;
        return;
    }
    int mid=(l+r) >> 1;
    if (y<=mid) query(v << 1,l,mid,x,y);
    else if (x>mid) query(v << 1 | 1,mid+1,r,x,y);
    else query(v << 1,l,mid,x,mid),query(v << 1 | 1,mid+1,r,mid+1,y);
}

int main(){
    scanf("%d%d",&n,&q);
    fo(i,1,n) {
        int x,y;
        scanf("%d%d",&x,&y);
        p[i]=1.0* x / y;
    }
    build(1,1,n);
    while (q--) {
        int Type,x,y,z;
        scanf("%d",&Type);
        if (Type==1) {
            scanf("%d%d%d",&x,&y,&z);
            p[x]=1.0 * y / z;
            change(1,1,n,x);
        }
        else {
            scanf("%d%d",&x,&y);
            db ans;
            now.a=1;
            now.b=0;
            query(1,1,n,x,y);
            if (now.b<=1e15) ans=1/(1+now.b);
            else ans=0;
            printf("%.10lf\n",ans);
        }
    }
    return 0;
}


//TLE算法。。估计只要改成线段树就能AC了。。
#include<cstdio>
#include<iostream>
#include<cmath>
#define xxx 100100
using namespace std;
double t[xxx],p[xxx],t1,t2,s[xxx],ans;
int n,q,type,l,r,x;

int main()
{
	scanf("%d%d",&n,&q);
	s[0]=1;
	for (int i=1;i<=n;i++)
	{
		scanf("%lf%lf",&t1,&t2);
		p[i]=t1/t2;
		t[i]=((double)1-p[i])/p[i];
		s[i]=s[i-1]*t[i];
	}
	while (q--)
	{
		scanf("%d",&type);
		if (type==1)
		{
			scanf("%d%lf%lf",&x,&t1,&t2);
			p[x]=t1/t2;
			t[x]=((double)1-p[x])/p[x];
			s[0]=1;
			for (int i=1;i<=n;i++)
				s[i]=s[i-1]*t[i];
		}
		else
		{
			scanf("%d%d",&l,&r);
			ans=1;
			for (int i=l;i<=r;i++)
				ans+=s[i]/s[l-1];
			if (ans>1e15) ans=0;
			else ans=(double)1/ans;
			printf("%.10lf\n",ans);
		}
	}
}


//TLE算法。。估计只要改成线段树就能AC了。。
%:pragma GCC optimize(3)
#include<cstdio>
#include<iostream>
#include<cmath>
#define xxx 100100
#define eps 0.00000000001
using namespace std;
double t[xxx],p[xxx],t1,t2,s[xxx],ans;
int n,q,type,l,r,x;

int main()
{
	scanf("%d%d",&n,&q);
	s[0]=1;
	for (int i=1;i<=n;i++)
	{
		scanf("%lf%lf",&t1,&t2);
		p[i]=t1/t2;
				if (abs(p[i])<=eps) while (1);
		t[i]=(1-p[i])/p[i];
		s[i]=s[i-1]*t[i];
	}
	while (q--)
	{
		scanf("%d",&type);
		if (type==1)
		{
			scanf("%d%lf%lf",&x,&t1,&t2);
			p[x]=t1/t2;
					if (abs(p[x])<=eps) while (1);
			t[x]=(1-p[x])/p[x];
			s[0]=1;
			for (int i=1;i<=n;i++)
				s[i]=s[i-1]*t[i];
		}
		else
		{
			scanf("%d%d",&l,&r);
			ans=1;
					if (s[l-1]<=eps) while(1);
			for (int i=l;i<=r;i++)
				ans+=s[i]/s[l-1];
					if (ans<=eps) while(1);
			if (ans>1e15) ans=0;
			else ans=1/ans;
			printf("%.10lf\n",ans);
		}
	}
}


#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fd(i,a,b) for(int i=a;i>=b;i--)
#define maxn 100005
#define db double
using namespace std;

struct seg{
    db a,b;
}t[maxn * 4],now;

int n,q;

db p[maxn];

void build(int v,int l,int r){
    if (l==r) {
        t[v].a=t[v].b=(1-p[l])/p[l];
        return;
    }
    int mid=(l+r) >> 1;
    build(v << 1,l,mid);
    build(v << 1 | 1,mid+1,r);
    t[v].a=t[v << 1].a*t[v << 1 | 1].a; if (t[v].a>1e310) while(1);
    t[v].b=t[v << 1].b+t[v << 1 | 1].b*t[v << 1].a;
}

void change(int v,int l,int r,int x){
    if (l==r) {
        t[v].a=t[v].b=(1-p[l])/p[l];
        return;
    }
    int mid=(l+r) >> 1;
    if (x<=mid) change(v << 1,l,mid,x);
    else change(v << 1 | 1,mid+1,r,x);
    t[v].a=t[v << 1].a*t[v << 1 | 1].a;
    t[v].b=t[v << 1].b+t[v << 1 | 1].b*t[v << 1].a;
}

void query(int v,int l,int r,int x,int y){
    if (l==x && r==y) {
        now.b=now.b+now.a*t[v].b;
        now.a=now.a*t[v].a;
        return;
    }
    int mid=(l+r) >> 1;
    if (y<=mid) query(v << 1,l,mid,x,y);
    else if (x>mid) query(v << 1 | 1,mid+1,r,x,y);
    else query(v << 1,l,mid,x,mid),query(v << 1 | 1,mid+1,r,mid+1,y);
}

int main(){
    scanf("%d%d",&n,&q);
    fo(i,1,n) {
        int x,y;
        scanf("%d%d",&x,&y);
        p[i]=1.0* x / y;
    }
    build(1,1,n);
    while (q--) {
        int Type,x,y,z;
        scanf("%d",&Type);
        if (Type==1) {
            scanf("%d%d%d",&x,&y,&z);
            p[x]=1.0 * y / z;
            change(1,1,n,x);
        }
        else {
            scanf("%d%d",&x,&y);
            db ans;
            now.a=1;
            now.b=0;
            query(1,1,n,x,y);
            if (now.b<=1e15) ans=1/(1+now.b);
            else ans=0;
            printf("%.10lf\n",ans);
        }
    }
    return 0;
}


#include<cstdio>
#include<iostream>
#include<cmath>
#define xxx 100100
using namespace std;
long double t[xxx],p[xxx],t1,t2,s[xxx],ans;
int n,q,type,l,r,x;

int main()
{
	scanf("%d%d",&n,&q);
	s[0]=1;
	for (int i=1;i<=n;i++)
	{
		cin>>t1>>t2;
		p[i]=t1/t2;
		t[i]=((double)1-p[i])/p[i];
		s[i]=s[i-1]*t[i];
		if (s[i]>1e4500) while(1);
	}
	while (q--)
	{
		cin>>type;
		if (type==1)
		{
			cin>>x>>t1>>t2;
			p[x]=t1/t2;
			t[x]=((double)1-p[x])/p[x];
			s[0]=1;
			for (int i=1;i<=n;i++)
			{
				s[i]=s[i-1]*t[i];
				if (s[i]>1e4500) while(1);
			}
		}
		else
		{
			cin>>l>>r;
			ans=0;
			for (int i=l;i<=r;i++)
				ans+=s[i]/s[l-1];
			if (ans>1e15) ans=0;
			else ans=(double)1/(ans+1);
			cout<<ans<<endl;
		}
	}
}


//TLE算法。。估计只要改成线段树就能AC了。。
%:pragma GCC optimize(3)
#include<cstdio>
#include<iostream>
#define xxx 100100
using namespace std;
long double t[xxx],p[xxx],t1,t2,s[xxx],ans,tem;
int n,q,type,l,r,x;

int main()
{
	scanf("%d%d",&n,&q);
	s[0]=1;
	for (int i=1;i<=n;i++)
	{
		scanf("%Lf%Lf",&t1,&t2);
		p[i]=t1/t2;
		t[i]=(1-p[i])/p[i];
		s[i]=s[i-1]*t[i];
	}
	while (q--)
	{
		scanf("%d",&type);
		if (type==1)
		{
			scanf("%d%Lf%Lf",&x,&t1,&t2);
			p[x]=t1/t2;
			t[x]=(1-p[x])/p[x];
			for (int i=x;i<=n;i++)
				s[i]=s[i-1]*t[i];
		}
		else
		{
			scanf("%d%d",&l,&r);
			ans=1;
			for (int i=l;i<=r;i++)
				ans+=s[i]/s[l-1];
			printf("%.10Lf\n",1/ans);
		}
	}
}


#include<cstdio>
#include<iostream>
#include<cmath>
#define mid ((l+r)>>1)
using namespace std;
double t[100100],t1,t2;
int n,q,type,st,en,w;
struct line_tree{
	double sum_up,single;
}tr[2332333],nil;
line_tree together(line_tree tr1,line_tree tr2){
	return (line_tree){tr1.sum_up+tr1.single*tr2.sum_up,tr1.single*tr2.single};
}
line_tree build(int x,int l,int r){
	if (l==r) return tr[x]=(line_tree){t[l],t[l]};
	return tr[x]=together(build(x<<1,l,mid),build(x<<1|1,mid+1,r));
}
line_tree change(int x,int l,int r,int p){
	if (l>p||r<p) return tr[x];
	if (l==r) return tr[x]=(line_tree){t[l],t[l]};
	return tr[x]=together(change(x<<1,l,mid,p),change(x<<1|1,mid+1,r,p));
}
line_tree que(int x,int l,int r,int st,int en){
	if (l>en||r<st) return nil;
	if (l==st&&r==en) return tr[x];
	return together(que(x<<1,l,mid,st,mid),que(x<<1|1,mid+1,r,mid+1,en));
}
int main()
{
	nil.single=1;nil.sum_up=0;
	scanf("%d%d",&n,&q);
	for (int i=1;i<=n;i++){
		cin>>t1>>t2;
		t[i]=(1.0-(t1/t2))/(t1/t2);
	}
	build(1,1,n);
	while (q--){
		cin>>type;
		if (type==1){
			cin>>w>>t1>>t2;
			t[w]=(1.0-(t1/t2))/(t1/t2);
			change(1,1,n,w);
		}
		else{
			cin>>st>>en;
			t1=que(1,1,n,st,en).sum_up;
			printf("%.10lf\n",t1>1e15?0:1.0/(t1+1));
		}
	}
}


//TLE算法。。估计只要改成线段树就能AC了。。
%:pragma GCC optimize(3)
#include<cstdio>
#include<iostream>
#define xxx 100100
using namespace std;
double t[xxx],p[xxx],t1,t2,s[xxx],ans;
int n,q,type,l,r,x;

int main()
{
	scanf("%d%d",&n,&q);
	s[0]=1;
	for (int i=1;i<=n;i++)
	{
		scanf("%lf%lf",&t1,&t2);
		p[i]=t1/t2;
		t[i]=(1-p[i])/p[i];
		s[i]=s[i-1]*t[i];
	}
	while (q--)
	{
		scanf("%d",&type);
		if (type==1)
		{
			scanf("%d%lf%lf",&x,&t1,&t2);
			p[x]=t1/t2;
			t[x]=(1-p[x])/p[x];
			s[0]=1;
			for (int i=1;i<=n;i++)
				s[i]=s[i-1]*t[i];
		}
		else
		{
			scanf("%d%d",&l,&r);
			ans=1;
			for (int i=l;i<=r;i++)
				ans+=s[i]/s[l-1];
			if (ans>1e15||ans==0) ans=0;
			else ans=1/ans;
			printf("%.10lf\n",ans);
		}
	}
}


#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

int n, m;
float u[100010];

struct node
{
	float prod, val;
};

const node naught{
	.prod = 1.0,
	.val = 0.0
};

inline node merge(node a, node b){
	return node {
		.prod = a.prod*b.prod,
		.val =  a.val + a.prod*b.val
	};
}

inline node makenode(float x){
	return node {
		.prod = x,
		.val = x
	};
}

int getmid(int l, int r){
	return l + (r-l)/2;
}

struct segtree
{
	node ar[400010];
	void init(int idx, int l, int r){
		if(l == r){
			ar[idx] = makenode(u[l]);
			return;
		}
		int mid = getmid(l, r);
		init(idx*2 + 0, l, mid);
		init(idx*2 + 1, mid+1, r);
		ar[idx] = merge(ar[idx*2+0], ar[idx*2+1]);
	}
	void upd(int idx, int l, int r, int x, float newval){
		if(l == r){
			ar[idx] = makenode(newval);
			return;
		}
		int mid = getmid(l, r);
		if(x <= mid){
			upd(idx*2 + 0, l, mid, x, newval);
		} else {
			upd(idx*2 + 1, mid+1, r, x, newval);
		}
		ar[idx] = merge(ar[idx*2+0], ar[idx*2+1]);
	}
	node query(int idx, int l, int r, int ql, int qr){
		if(l > qr or r < ql){
			return naught;
		}
		if(ql <= l and qr >= r){
			return ar[idx];
		}
		int mid = getmid(l, r);
		node lnode = query(idx*2 + 0, l, mid, ql, qr),
		rnode = query(idx*2 + 1, mid+1, r, ql, qr);
		return merge(
			lnode, rnode
		);
	}
};

segtree tree;

int main(){
	//ios_base::sync_with_stdio(false);
	//cin.tie(nullptr);
	scanf("%d %d", &n, &m);
	for (int i = 0; i < n; ++i)
	{
		int a, b;
		scanf("%d %d", &a, &b);
		float p = (0.0+a)/b;
		u[i] = (1.0-p)/p;
	}
	tree.init(1, 0, n-1);
	for (int i = 0; i < m; ++i)
	{
		int x, idx, a, b;
		scanf("%d", &x);
		if(x == 1){
			scanf("%d %d %d", &idx, &a, &b);
			float p = (1.0*a)/b;
			tree.upd(1, 0, n-1, idx-1, (1-p)/p);
		} else {
			scanf("%d %d", &a, &b);
			node tmp = tree.query(1, 0, n-1, a-1, b-1);
			float ans = (1.0 + tmp.val);
			//	cout << setprecision(6) << fixed << 1.0/ans << "\n";
			printf("%.6f\n", 1.0/ans);
		}
	}
}


#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

int n, m;
double u[100010];

struct node
{
	double prod, val;
};

node merge(node a, node b){
	double fr, sc;
	if(a.prod < 1e-12 or b.prod < 1e-12){
		fr = 0.0;
	} else {
		fr = a.prod*b.prod;
	}
	if(a.prod < 1e-12 or b.val < 1e-12){
		sc = 0.0;
	} else {
		sc = a.prod*b.val;
	}
	return node {fr, a.val + sc};
}

int getmid(int l, int r){
	return l + (r-l)/2;
}

struct segtree
{
	node ar[400010];
	void init(int idx, int l, int r){
		if(l == r){
			ar[idx].prod = u[l];
			ar[idx].val = u[l];
			return;
		}
		int mid = getmid(l, r);
		init(idx*2 + 1, l, mid);
		init(idx*2 + 2, mid+1, r);
		ar[idx] = merge(ar[idx*2+1], ar[idx*2+2]);
	}
	void upd(int idx, int l, int r, int x, double newval){
		if(l == r){
			ar[idx].prod = newval;
			ar[idx].val = newval;
			return;
		}
		int mid = getmid(l, r);
		if(x <= mid){
			upd(idx*2 + 1, l, mid, x, newval);
		} else {
			upd(idx*2 + 2, mid+1, r, x, newval);
		}
		ar[idx] = merge(ar[idx*2+1], ar[idx*2+2]);
	}
	node query(int idx, int l, int r, int ql, int qr){
		if(l > qr or r < ql){
			return node {1.0, 0.0};
		}
		if(ql <= l and qr >= r){
			return ar[idx];
		}
		int mid = getmid(l, r);
		return merge(query(idx*2 + 1, l, mid, ql, qr),
		query(idx*2 + 2, mid+1, r, ql, qr)
		);
	}
};

segtree tree;

int main(){
	ios_base::sync_with_stdio(false);
	cin.tie(nullptr);
	cin >> n >> m;
	for (int i = 0; i < n; ++i)
	{
		int a, b;
		cin >> a >> b;
		double p = (0.0+a)/b;
		u[i] = (1.0-p)/p;
	}
	tree.init(0, 0, n-1);
	for (int i = 0; i < m; ++i)
	{
		int x, idx, a, b;
		cin >> x;
		if(x == 1){
			cin >> idx >> a >> b;
			double p = (1.0*a)/b;
			tree.upd(0, 0, n-1, idx-1, (1-p)/p);
		} else {
			cin >> a >> b;
			node tmp = tree.query(0, 0, n-1, a-1, b-1);
			double ans = (1.0 + tmp.val);
			//if(isnan(ans) or ans >= 1e30){
			//	cout << setprecision(10) << fixed << 0.0 << "\n";
			//} else {
				cout << setprecision(10) << fixed << 1.0/ans << "\n";
			//}
		}
	}
}


#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

int n, m;
float u[100010];

struct node
{
	float prod, val;
};

const node naught{
	.prod = 1.0,
	.val = 0.0
};

inline node merge(node a, node b){
	return node {
		.prod = a.prod*b.prod,
		.val =  a.val + a.prod*b.val
	};
}

inline node makenode(float x){
	return node {
		.prod = x,
		.val = x
	};
}

int getmid(int l, int r){
	return l + (r-l)/2;
}

struct segtree
{
	node ar[400010];
	void init(int idx, int l, int r){
		if(l == r){
			ar[idx] = makenode(u[l]);
			return;
		}
		int mid = getmid(l, r);
		init(idx*2 + 0, l, mid);
		init(idx*2 + 1, mid+1, r);
		ar[idx] = merge(ar[idx*2+0], ar[idx*2+1]);
	}
	void upd(int idx, int l, int r, int x, float newval){
		if(l == r){
			ar[idx] = makenode(newval);
			return;
		}
		int mid = getmid(l, r);
		if(x <= mid){
			upd(idx*2 + 0, l, mid, x, newval);
		} else {
			upd(idx*2 + 1, mid+1, r, x, newval);
		}
		ar[idx] = merge(ar[idx*2+0], ar[idx*2+1]);
	}
	node query(int idx, int l, int r, int ql, int qr){
		if(l > qr or r < ql){
			return naught;
		}
		if(ql <= l and qr >= r){
			return ar[idx];
		}
		int mid = getmid(l, r);
		node lnode = query(idx*2 + 0, l, mid, ql, min(qr, mid)),
		rnode = query(idx*2 + 1, mid+1, r, max(ql, mid+1), qr);
		return merge(
			lnode, rnode
		);
	}
};

segtree tree;

int main(){
	//ios_base::sync_with_stdio(false);
	//cin.tie(nullptr);
	scanf("%d %d", &n, &m);
	for (int i = 0; i < n; ++i)
	{
		int a, b;
		scanf("%d %d", &a, &b);
		float p = (0.0+a)/b;
		u[i] = (1.0-p)/p;
	}
	tree.init(1, 0, n-1);
	for (int i = 0; i < m; ++i)
	{
		int x, idx, a, b;
		scanf("%d", &x);
		if(x == 1){
			scanf("%d %d %d", &idx, &a, &b);
			float p = (1.0*a)/b;
			tree.upd(1, 0, n-1, idx-1, (1-p)/p);
		} else {
			scanf("%d %d", &a, &b);
			node tmp = tree.query(1, 0, n-1, a-1, b-1);
			float ans = (1.0 + tmp.val);
			//	cout << setprecision(6) << fixed << 1.0/ans << "\n";
			printf("%.6f\n", 1.0/ans);
		}
	}
}


#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

int n, m;
double u[100010];

struct node
{
	double prod, val;
};

node merge(node a, node b){
	double fr, sc;
	if(a.prod < 1e-6 or b.prod < 1e-6){
		fr = 0.0;
	} else {
		fr = a.prod*b.prod;
	}
	if(a.prod < 1e-6 or b.val < 1e-6){
		sc = 0.0;
	} else {
		sc = a.prod*b.val;
	}
	return node {fr, a.val + sc};
}

int getmid(int l, int r){
	return l + (r-l)/2;
}

struct segtree
{
	node ar[400010];
	void init(int idx, int l, int r){
		if(l == r){
			ar[idx].prod = u[l];
			ar[idx].val = u[l];
			return;
		}
		int mid = getmid(l, r);
		init(idx*2 + 1, l, mid);
		init(idx*2 + 2, mid+1, r);
		ar[idx] = merge(ar[idx*2+1], ar[idx*2+2]);
	}
	void upd(int idx, int l, int r, int x, double newval){
		if(l == r){
			ar[idx].prod = newval;
			ar[idx].val = newval;
			return;
		}
		int mid = getmid(l, r);
		if(x <= mid){
			upd(idx*2 + 1, l, mid, x, newval);
		} else {
			upd(idx*2 + 2, mid+1, r, x, newval);
		}
		ar[idx] = merge(ar[idx*2+1], ar[idx*2+2]);
	}
	node query(int idx, int l, int r, int ql, int qr){
		if(l > qr or r < ql){
			return node {1.0, 0.0};
		}
		if(ql <= l and qr >= r){
			return ar[idx];
		}
		int mid = getmid(l, r);
		return merge(query(idx*2 + 1, l, mid, ql, qr),
		query(idx*2 + 2, mid+1, r, ql, qr)
		);
	}
};

segtree tree;

int main(){
	ios_base::sync_with_stdio(false);
	cin.tie(nullptr);
	cin >> n >> m;
	for (int i = 0; i < n; ++i)
	{
		int a, b;
		cin >> a >> b;
		double p = (0.0+a)/b;
		u[i] = (1.0-p)/p;
	}
	tree.init(0, 0, n-1);
	for (int i = 0; i < m; ++i)
	{
		int x, idx, a, b;
		cin >> x;
		if(x == 1){
			cin >> idx >> a >> b;
			double p = (1.0*a)/b;
			tree.upd(0, 0, n-1, idx-1, (1-p)/p);
		} else {
			cin >> a >> b;
			node tmp = tree.query(0, 0, n-1, a-1, b-1);
			double ans = (1.0 + tmp.val);
			//if(isnan(ans) or ans >= 1e30){
			//	cout << setprecision(10) << fixed << 0.0 << "\n";
			//} else {
				cout << setprecision(10) << fixed << 1.0/ans << "\n";
			//}
		}
	}
}


#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

int n, m;
double u[100010];

struct node
{
	double prod, val;
};

node merge(node a, node b){
	double fr, sc;
	if(a.prod < 1e-9 and b.prod < 1e-9){
		fr = 0.0;
	} else {
		fr = a.prod*b.prod;
	}
	if(a.prod < 1e-9 and b.val < 1e-9){
		sc = 0.0;
	} else {
		sc = a.prod*b.val;
	}
	return node {fr, a.val + sc};
}

int getmid(int l, int r){
	return l + (r-l)/2;
}

struct segtree
{
	node ar[400010];
	void init(int idx, int l, int r){
		if(l == r){
			ar[idx].prod = u[l];
			ar[idx].val = u[l];
			return;
		}
		int mid = getmid(l, r);
		init(idx*2 + 1, l, mid);
		init(idx*2 + 2, mid+1, r);
		ar[idx] = merge(ar[idx*2+1], ar[idx*2+2]);
	}
	void upd(int idx, int l, int r, int x, double newval){
		if(l == r){
			ar[idx].prod = newval;
			ar[idx].val = newval;
			return;
		}
		int mid = getmid(l, r);
		if(x <= mid){
			upd(idx*2 + 1, l, mid, x, newval);
		} else {
			upd(idx*2 + 2, mid+1, r, x, newval);
		}
		ar[idx] = merge(ar[idx*2+1], ar[idx*2+2]);
	}
	node query(int idx, int l, int r, int ql, int qr){
		if(l > qr or r < ql){
			return node {1.0, 0.0};
		}
		if(ql <= l and qr >= r){
			return ar[idx];
		}
		int mid = getmid(l, r);
		return merge(query(idx*2 + 1, l, mid, ql, qr),
		query(idx*2 + 2, mid+1, r, ql, qr)
		);
	}
};

segtree tree;

int main(){
	ios_base::sync_with_stdio(false);
	cin.tie(nullptr);
	cin >> n >> m;
	for (int i = 0; i < n; ++i)
	{
		int a, b;
		cin >> a >> b;
		double p = (0.0+a)/b;
		u[i] = (1.0-p)/p;
	}
	tree.init(0, 0, n-1);
	for (int i = 0; i < m; ++i)
	{
		int x, idx, a, b;
		cin >> x;
		if(x == 1){
			cin >> idx >> a >> b;
			double p = (1.0*a)/b;
			tree.upd(0, 0, n-1, idx-1, (1-p)/p);
		} else {
			cin >> a >> b;
			node tmp = tree.query(0, 0, n-1, a-1, b-1);
			double ans = (1.0 + tmp.val);
			//if(isnan(ans) or ans >= 1e30){
			//	cout << setprecision(10) << fixed << 0.0 << "\n";
			//} else {
				cout << setprecision(10) << fixed << 1.0/ans << "\n";
			//}
		}
	}
}


#include <bits/stdc++.h>
using namespace std;
#define rep(i, a, b) for(register int i = a; i <= b; i++)
#define per(i, a, b) for(register int i = a; i >= b; i--)
typedef long long LL;
const LL mod = 1e9 + 7;
const int N = 1e5 + 5;

int n, q, a[N], b[N];
double g[N], p[N];
struct Tree {
	double val[N<<2], mul[N<<2];
	void build_(int o, int l, int r) {
		mul[o] = 1;
		if (l == r) val[o] = g[l];
		else {
			int mid = (l + r)>>1;
			build_(o<<1, l, mid), build_(o<<1|1, mid + 1, r);
			val[o] = val[o<<1] + val[o<<1|1];
		}
	}
	void push_down(int o) {
		int ls = o<<1, rs = o<<1|1;
		mul[ls] *= mul[o], mul[rs] *= mul[o];
		val[ls] *= mul[o], val[rs] *= mul[o];
		mul[o] = 1;
	}
	void update_(int o, int l, int r, int x, int y, double k) {
		if (x <= l && r <= y) {
			mul[o] *= k, val[o] *= k;
			return;
		}
		int mid = (l + r)>>1;
		if (fabs(mul[o] - 1.0) > 1e-5) push_down(o);
		if (x <= mid) update_(o<<1, l, mid, x, y, k);
		if (mid < y) update_(o<<1|1, mid + 1, r, x, y, k);
		val[o] = val[o<<1] + val[o<<1|1];
	}
	double query_(int o, int l, int r, int x, int y) {
		if (x > y) return 0;
		if (x <= l && r <= y) return val[o];

		if (fabs(mul[o] - 1.0) > 1e-5) push_down(o);
		int mid = (l + r)>>1;
		double ans = 0;

		if (x <= mid) ans += query_(o<<1, l, mid, x, y);
		if (mid < y) ans += query_(o<<1|1, mid + 1, r, x, y);

		return ans;
	}
} T;

int main() {
	cin>>n>>q;

	rep (i, 1, n) {
		scanf("%d%d", &a[i], &b[i]);
		p[i] = 1.0*(b[i] - a[i])/a[i];
		g[i] = i == 1 ? p[i] : g[i - 1]*p[i];
	}

	T.build_(1, 1, n);

	while (q--) {
		int id, x, y, c, d;
		scanf("%d%d", &id, &x);
		if (id == 1) {
			scanf("%d%d", &c, &d);
			double w = 1.0*(d - c)/c;
			T.update_(1, 1, n, x, n, w/p[x]);
			p[x] = w;
		} else {
			scanf("%d", &y);
			double res = T.query_(1, 1, n, x + 1, y), k = T.query_(1, 1, n, x, x);
			if (fabs(res - k) <= 1e-7) res = 1;
			else res /= k;
			res = -res*p[x] - p[x];
			printf("%.7f\n", 1/(1 - res));
		}
	}

	return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define rep(i, a, b) for(register int i = a; i <= b; i++)
#define per(i, a, b) for(register int i = a; i >= b; i--)
typedef long long LL;
const LL mod = 1e9 + 7;
const int N = 1e5 + 5;

int n, q, a[N], b[N];
double g[N], p[N];
struct Tree {
	double val[N<<2], mul[N<<2];
	void build_(int o, int l, int r) {
		mul[o] = 1;
		if (l == r) val[o] = g[l];
		else {
			int mid = (l + r)>>1;
			build_(o<<1, l, mid), build_(o<<1|1, mid + 1, r);
			val[o] = val[o<<1] + val[o<<1|1];
		}
	}
	void push_down(int o) {
		int ls = o<<1, rs = o<<1|1;
		mul[ls] *= mul[o], mul[rs] *= mul[o];
		val[ls] *= mul[o], val[rs] *= mul[o];
		mul[o] = 1;
	}
	void update_(int o, int l, int r, int x, int y, double k) {
		if (x <= l && r <= y) {
			mul[o] *= k, val[o] *= k;
			return;
		}
		int mid = (l + r)>>1;
		if (fabs(mul[o] - 1.0) > 1e-8) push_down(o);
		if (x <= mid) update_(o<<1, l, mid, x, y, k);
		if (mid < y) update_(o<<1|1, mid + 1, r, x, y, k);
		val[o] = val[o<<1] + val[o<<1|1];
	}
	double query_(int o, int l, int r, int x, int y) {
		if (x > y) return 0;
		if (x <= l && r <= y) return val[o];

		if (fabs(mul[o] - 1.0) > 1e-8) push_down(o);
		int mid = (l + r)>>1;
		double ans = 0;

		if (x <= mid) ans += query_(o<<1, l, mid, x, y);
		if (mid < y) ans += query_(o<<1|1, mid + 1, r, x, y);

		return ans;
	}
} T;

int main() {
	cin>>n>>q;

	rep (i, 1, n) {
		scanf("%d%d", &a[i], &b[i]);
		p[i] = 1.0*a[i]/b[i];
		p[i] = (1.0 - p[i])/p[i];
		g[i] = i == 1 ? p[i] : g[i - 1]*p[i];
	}

	T.build_(1, 1, n);

	while (q--) {
		int id, x, y, c, d;
		scanf("%d%d", &id, &x);
		if (id == 1) {
			scanf("%d%d", &c, &d);
			double w = (double)c/d;
			w = (1 - w)/w;
			T.update_(1, 1, n, x, n, w/p[x]);
			p[x] = w;
		} else {
			scanf("%d", &y);
			double res = T.query_(1, 1, n, x + 1, y)/T.query_(1, 1, n, x, x);
			res = -res*p[x] - p[x];
			printf("%.12f\n", 1.0/(1.0 - res));
		}
	}

	return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define rep(i, a, b) for(register int i = a; i <= b; i++)
#define per(i, a, b) for(register int i = a; i >= b; i--)
typedef long long LL;
const LL mod = 1e9 + 7;
const int N = 1e5 + 5;

int n, q, a[N], b[N];
double g[N], p[N];
struct Tree {
	double val[N<<2], mul[N<<2];
	void build_(int o, int l, int r) {
		mul[o] = 1;
		if (l == r) val[o] = g[l];
		else {
			int mid = (l + r)>>1;
			build_(o<<1, l, mid), build_(o<<1|1, mid + 1, r);
			val[o] = val[o<<1] + val[o<<1|1];
		}
	}
	void push_down(int o) {
		int ls = o<<1, rs = o<<1|1;
		mul[ls] *= mul[o], mul[rs] *= mul[o];
		val[ls] *= mul[o], val[rs] *= mul[o];
		mul[o] = 1;
	}
	void update_(int o, int l, int r, int x, int y, double k) {
		if (x <= l && r <= y) {
			mul[o] *= k, val[o] *= k;
			return;
		}
		int mid = (l + r)>>1;
		if (fabs(mul[o] - 1.0) > 1e-5) push_down(o);
		if (x <= mid) update_(o<<1, l, mid, x, y, k);
		if (mid < y) update_(o<<1|1, mid + 1, r, x, y, k);
		val[o] = val[o<<1] + val[o<<1|1];
	}
	double query_(int o, int l, int r, int x, int y) {
		if (x > y) return 0;
		if (x <= l && r <= y) return val[o];

		if (fabs(mul[o] - 1.0) > 1e-5) push_down(o);
		int mid = (l + r)>>1;
		double ans = 0;

		if (x <= mid) ans += query_(o<<1, l, mid, x, y);
		if (mid < y) ans += query_(o<<1|1, mid + 1, r, x, y);

		return ans;
	}
} T;

int main() {
	cin>>n>>q;

	rep (i, 1, n) {
		scanf("%d%d", &a[i], &b[i]);
		p[i] = 1.0*(b[i] - a[i])/a[i];
		g[i] = i == 1 ? p[i] : g[i - 1]*p[i];
	}

	T.build_(1, 1, n);

	while (q--) {
		int id, x, y, c, d;
		scanf("%d%d", &id, &x);
		if (id == 1) {
			scanf("%d%d", &c, &d);
			double w = 1.0*(d - c)/c;
			T.update_(1, 1, n, x, n, w/p[x]);
			p[x] = w;
		} else {
			scanf("%d", &y);
			double res = T.query_(1, 1, n, x + 1, y), k = T.query_(1, 1, n, x, x);
			if (fabs(k) <= 1e-7) res *= 1e18;
			else res /= k;
			res = -res*p[x] - p[x];
			printf("%.7f\n", 1/(1 - res));
		}
	}

	return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define rep(i, a, b) for(register int i = a; i <= b; i++)
#define per(i, a, b) for(register int i = a; i >= b; i--)
typedef long long LL;
const LL mod = 1e9 + 7;
const int N = 1e5 + 5;

int n, q, a[N], b[N];
long double g[N], p[N];
struct Tree {
	long double val[N<<2], mul[N<<2];
	void build_(int o, int l, int r) {
		mul[o] = 1;
		if (l == r) val[o] = g[l];
		else {
			int mid = (l + r)>>1;
			build_(o<<1, l, mid), build_(o<<1|1, mid + 1, r);
			val[o] = val[o<<1] + val[o<<1|1];
		}
	}
	void push_down(int o) {
		int ls = o<<1, rs = o<<1|1;
		mul[ls] *= mul[o], mul[rs] *= mul[o];
		val[ls] *= mul[o], val[rs] *= mul[o];
		mul[o] = 1;
	}
	void update_(int o, int l, int r, int x, int y, long double k) {
		if (x <= l && r <= y) {
			mul[o] *= k, val[o] *= k;
			return;
		}
		int mid = (l + r)>>1;
		if (fabs(mul[o] - 1.0) > 1e-8) push_down(o);
		if (x <= mid) update_(o<<1, l, mid, x, y, k);
		if (mid < y) update_(o<<1|1, mid + 1, r, x, y, k);
		val[o] = val[o<<1] + val[o<<1|1];
	}
	long double query_(int o, int l, int r, int x, int y) {
		if (x > y) return 0;
		if (x <= l && r <= y) return val[o];

		if (abs(mul[o] - 1.0) > 1e-8) push_down(o);
		int mid = (l + r)>>1;
		long double ans = 0;

		if (x <= mid) ans += query_(o<<1, l, mid, x, y);
		if (mid < y) ans += query_(o<<1|1, mid + 1, r, x, y);

		return ans;
	}
} T;

int main() {
	cin>>n>>q;

	rep (i, 1, n) {
		scanf("%d%d", &a[i], &b[i]);
		p[i] = 1.0*a[i]/b[i];
		p[i] = (1.0 - p[i])/p[i];
		g[i] = i == 1 ? p[i] : g[i - 1]*p[i];
	}

	T.build_(1, 1, n);

	while (q--) {
		int id, x, y, c, d;
		scanf("%d%d", &id, &x);
		if (id == 1) {
			scanf("%d%d", &c, &d);
			long double w = 1.0*c/d;
			w = (1 - w)/w;
			T.update_(1, 1, n, x, n, w/p[x]);
			p[x] = w;
		} else {
			scanf("%d", &y);
			long double res = T.query_(1, 1, n, x + 1, y)/T.query_(1, 1, n, x, x);
			res = -res*p[x] - p[x];
			printf("%.12Lf\n", 1/(1 - res));
		}
	}

	return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define rep(i, a, b) for(register int i = a; i <= b; i++)
#define per(i, a, b) for(register int i = a; i >= b; i--)
typedef long long LL;
const LL mod = 1e9 + 7;
const int N = 1e5 + 5;

int n, q, a[N], b[N];
double g[N], p[N];
struct Tree {
	double val[N<<2], mul[N<<2];
	void build_(int o, int l, int r) {
		mul[o] = 1;
		if (l == r) val[o] = g[l];
		else {
			int mid = (l + r)>>1;
			build_(o<<1, l, mid), build_(o<<1|1, mid + 1, r);
			val[o] = val[o<<1] + val[o<<1|1];
		}
	}
	void push_down(int o) {
		int ls = o<<1, rs = o<<1|1;
		mul[ls] *= mul[o], mul[rs] *= mul[o];
		val[ls] *= mul[o], val[rs] *= mul[o];
		mul[o] = 1;
	}
	void update_(int o, int l, int r, int x, int y, double k) {
		if (x <= l && r <= y) {
			mul[o] *= k, val[o] *= k;
			return;
		}
		int mid = (l + r)>>1;
		if (fabs(mul[o] - 1.0) > 1e-8) push_down(o);
		if (x <= mid) update_(o<<1, l, mid, x, y, k);
		if (mid < y) update_(o<<1|1, mid + 1, r, x, y, k);
		val[o] = val[o<<1] + val[o<<1|1];
	}
	double query_(int o, int l, int r, int x, int y) {
		if (x > y) return 0;
		if (x <= l && r <= y) return val[o];

		if (fabs(mul[o] - 1.0) > 1e-8) push_down(o);
		int mid = (l + r)>>1;
		double ans = 0;

		if (x <= mid) ans += query_(o<<1, l, mid, x, y);
		if (mid < y) ans += query_(o<<1|1, mid + 1, r, x, y);

		return ans;
	}
} T;

int main() {
	cin>>n>>q;

	rep (i, 1, n) {
		scanf("%d%d", &a[i], &b[i]);
		p[i] = 1.0*a[i]/b[i];
		p[i] = (1.0 - p[i])/p[i];
		g[i] = i == 1 ? p[i] : g[i - 1]*p[i];
	}

	T.build_(1, 1, n);

	while (q--) {
		int id, x, y, c, d;
		scanf("%d%d", &id, &x);
		if (id == 1) {
			scanf("%d%d", &c, &d);
			double w = (double)c/d;
			w = (1 - w)/w;
			T.update_(1, 1, n, x, n, w/p[x]);
			p[x] = w;
		} else {
			scanf("%d", &y);
			double res = T.query_(1, 1, n, x + 1, y)/T.query_(1, 1, n, x, x);
			res = -res*p[x] - p[x];
			printf("%.7f\n", 1.0/(1.0 - res));
		}
	}

	return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define rep(i, a, b) for(register int i = a; i <= b; i++)
#define per(i, a, b) for(register int i = a; i >= b; i--)
typedef long long LL;
const LL mod = 1e9 + 7;
const int N = 1e5 + 5;

int n, q, a[N], b[N];
double g[N], p[N];
struct Tree {
	double val[N<<2], mul[N<<2];
	void build_(int o, int l, int r) {
		mul[o] = 1;
		if (l == r) val[o] = g[l];
		else {
			int mid = (l + r)>>1;
			build_(o<<1, l, mid), build_(o<<1|1, mid + 1, r);
			val[o] = val[o<<1] + val[o<<1|1];
		}
	}
	void push_down(int o) {
		int ls = o<<1, rs = o<<1|1;
		mul[ls] *= mul[o], mul[rs] *= mul[o];
		val[ls] *= mul[o], val[rs] *= mul[o];
		mul[o] = 1;
	}
	void update_(int o, int l, int r, int x, int y, long double k) {
		if (x <= l && r <= y) {
			mul[o] *= k, val[o] *= k;
			return;
		}
		int mid = (l + r)>>1;
		if (fabs(mul[o] - 1.0) > 1e-8) push_down(o);
		if (x <= mid) update_(o<<1, l, mid, x, y, k);
		if (mid < y) update_(o<<1|1, mid + 1, r, x, y, k);
		val[o] = val[o<<1] + val[o<<1|1];
	}
	long double query_(int o, int l, int r, int x, int y) {
		if (x > y) return 0;
		if (x <= l && r <= y) return val[o];

		if (fabs(mul[o] - 1.0) > 1e-8) push_down(o);
		int mid = (l + r)>>1;
		double ans = 0;

		if (x <= mid) ans += query_(o<<1, l, mid, x, y);
		if (mid < y) ans += query_(o<<1|1, mid + 1, r, x, y);

		return ans;
	}
} T;

int main() {
	cin>>n>>q;

	rep (i, 1, n) {
		scanf("%d%d", &a[i], &b[i]);
		p[i] = 1.0*a[i]/b[i];
		p[i] = (1.0 - p[i])/p[i];
		g[i] = i == 1 ? p[i] : g[i - 1]*p[i];
	}

	T.build_(1, 1, n);

	while (q--) {
		int id, x, y, c, d;
		scanf("%d%d", &id, &x);
		if (id == 1) {
			scanf("%d%d", &c, &d);
			double w = (double)c/d;
			w = (1 - w)/w;
			T.update_(1, 1, n, x, n, w/p[x]);
			p[x] = w;
		} else {
			scanf("%d", &y);
			double res = T.query_(1, 1, n, x + 1, y)/T.query_(1, 1, n, x, x);
			res = -res*p[x] - p[x];
			printf("%.12f\n", 1/(1 - res));
		}
	}

	return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define rep(i, a, b) for(register int i = a; i <= b; i++)
#define per(i, a, b) for(register int i = a; i >= b; i--)
typedef long long LL;
const LL mod = 1e9 + 7;
const int N = 1e5 + 5;

int n, q, a[N], b[N];
double g[N], p[N];
struct Tree {
	double val[N<<2], mul[N<<2];
	void build_(int o, int l, int r) {
		mul[o] = 1;
		if (l == r) val[o] = g[l];
		else {
			int mid = (l + r)>>1;
			build_(o<<1, l, mid), build_(o<<1|1, mid + 1, r);
			val[o] = val[o<<1] + val[o<<1|1];
		}
	}
	void push_down(int o) {
		int ls = o<<1, rs = o<<1|1;
		mul[ls] *= mul[o], mul[rs] *= mul[o];
		val[ls] *= mul[o], val[rs] *= mul[o];
		mul[o] = 1;
	}
	void update_(int o, int l, int r, int x, int y, double k) {
		if (x <= l && r <= y) {
			mul[o] *= k, val[o] *= k;
			return;
		}
		int mid = (l + r)>>1;
		if (fabs(mul[o] - 1.0) > 1e-5) push_down(o);
		if (x <= mid) update_(o<<1, l, mid, x, y, k);
		if (mid < y) update_(o<<1|1, mid + 1, r, x, y, k);
		val[o] = val[o<<1] + val[o<<1|1];
	}
	double query_(int o, int l, int r, int x, int y) {
		if (x > y) return 0;
		if (x <= l && r <= y) return val[o];

		if (fabs(mul[o] - 1.0) > 1e-5) push_down(o);
		int mid = (l + r)>>1;
		double ans = 0;

		if (x <= mid) ans += query_(o<<1, l, mid, x, y);
		if (mid < y) ans += query_(o<<1|1, mid + 1, r, x, y);

		return ans;
	}
} T;

int main() {
	cin>>n>>q;

	rep (i, 1, n) {
		scanf("%d%d", &a[i], &b[i]);
		p[i] = 1.0*(b[i] - a[i])/a[i];
		g[i] = i == 1 ? p[i] : g[i - 1]*p[i];
	}

	T.build_(1, 1, n);

	while (q--) {
		int id, x, y, c, d;
		scanf("%d%d", &id, &x);
		if (id == 1) {
			scanf("%d%d", &c, &d);
			double w = 1.0*(d - c)/c;
			T.update_(1, 1, n, x, n, w/p[x]);
			p[x] = w;
		} else {
			scanf("%d", &y);
			double res = T.query_(1, 1, n, x + 1, y), k = T.query_(1, 1, n, x, x);
			if (fabs(res - k) <= 1e-7) res = 1;
			res = -res*p[x] - p[x];
			printf("%.7f\n", k/(k - res));
		}
	}

	return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define rep(i, a, b) for(register int i = a; i <= b; i++)
#define per(i, a, b) for(register int i = a; i >= b; i--)
typedef long long LL;
typedef pair <double, double> P;
const LL mod = 1e9 + 7;
const int N = 1e5 + 5;

int n, q, a, b;
struct Tree {
	double val[N<<2], w[N<<2];

	void push_up(int o) {
		int ls = o<<1, rs = ls|1;
		val[o] = val[ls] + w[ls]*val[rs];
		w[o] = w[ls]*w[rs];
	}

	void update_(int o, int l, int r, int x, double k) {
		if (l == r) {
			val[o] = w[o] = k;
			return;
		}
		int mid = (l + r)>>1;
		if (x <= mid) update_(o<<1, l, mid, x, k);
		else update_(o<<1|1, mid + 1, r, x, k);
		push_up(o);
	}

	P query_(int o, int l, int r, int x, int y) {
		if (x <= l && r <= y)
			return P(val[o], w[o]);
		int mid = (l + r)>>1;
		P ans = P(0, 1);

		if (x <= mid) {
			P cur = query_(o<<1, l, mid, x, y);
			ans.first += ans.second*cur.first;
			ans.second *= cur.second;
		}

		if (mid < y) {
			P cur = query_(o<<1|1, mid + 1, r, x, y);
			ans.first += ans.second*cur.first;
			ans.second *= cur.second;
		}

		return ans;
	}
} T;

int main() {
	cin>>n>>q;

	rep (i, 1, n) {
		scanf("%d%d", &a, &b);
		T.update_(1, 1, n, i, 1.0*(b - a)/a);
	}

	while (q--) {
		int typ, x, y;
		scanf("%d", &typ);

		if (typ == 1) {
			scanf("%d%d%d", &x, &a, &b);
			T.update_(1, 1, n, x, 1.0*(b - a)/a);
		} else {
			scanf("%d%d", &x, &y);
			double ans = T.query_(1, 1, n, x, y).first;
			printf("%.9f\n", 1/(1 + ans));
		}
	}

	return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define rep(i, a, b) for(register int i = a; i <= b; i++)
#define per(i, a, b) for(register int i = a; i >= b; i--)
typedef long long LL;
const LL mod = 1e9 + 7;
const int N = 1e5 + 5;

int n, q, a[N], b[N];
double g[N], p[N];
struct Tree {
	double val[N<<2], mul[N<<2];
	void build_(int o, int l, int r) {
		mul[o] = 1;
		if (l == r) val[o] = g[l];
		else {
			int mid = (l + r)>>1;
			build_(o<<1, l, mid), build_(o<<1|1, mid + 1, r);
			val[o] = val[o<<1] + val[o<<1|1];
		}
	}
	void push_down(int o) {
		int ls = o<<1, rs = o<<1|1;
		mul[ls] *= mul[o], mul[rs] *= mul[o];
		val[ls] *= mul[o], val[rs] *= mul[o];
		mul[o] = 1;
	}
	void update_(int o, int l, int r, int x, int y, double k) {
		if (x <= l && r <= y) {
			mul[o] *= k, val[o] *= k;
			return;
		}
		int mid = (l + r)>>1;
		if (fabs(mul[o] - 1.0) > 1e-5) push_down(o);
		if (x <= mid) update_(o<<1, l, mid, x, y, k);
		if (mid < y) update_(o<<1|1, mid + 1, r, x, y, k);
		val[o] = val[o<<1] + val[o<<1|1];
	}
	double query_(int o, int l, int r, int x, int y) {
		if (x > y) return 0;
		if (x <= l && r <= y) return val[o];

		if (fabs(mul[o] - 1.0) > 1e-5) push_down(o);
		int mid = (l + r)>>1;
		double ans = 0;

		if (x <= mid) ans += query_(o<<1, l, mid, x, y);
		if (mid < y) ans += query_(o<<1|1, mid + 1, r, x, y);

		return ans;
	}
} T;

int main() {
	cin>>n>>q;

	rep (i, 1, n) {
		scanf("%d%d", &a[i], &b[i]);
		p[i] = 1.0*a[i]/b[i];
		p[i] = (1.0 - p[i])/p[i];
		g[i] = i == 1 ? p[i] : g[i - 1]*p[i];
	}

	T.build_(1, 1, n);

	while (q--) {
		int id, x, y, c, d;
		scanf("%d%d", &id, &x);
		if (id == 1) {
			scanf("%d%d", &c, &d);
			double w = 1.0*c/d;
			w = (1 - w)/w;
			T.update_(1, 1, n, x, n, w/p[x]);
			p[x] = w;
		} else {
			scanf("%d", &y);
			double res = T.query_(1, 1, n, x + 1, y), k = T.query_(1, 1, n, x, x);
			res = -res*p[x] - k*p[x];
			printf("%.7f\n", k/(k - res));
		}
	}

	return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define rep(i, a, b) for(register int i = a; i <= b; i++)
#define per(i, a, b) for(register int i = a; i >= b; i--)
typedef long long LL;
#define double long double
const LL mod = 1e9 + 7;
const int N = 1e5 + 5;

int n, q, a[N], b[N];
double g[N], p[N];
struct Tree {
	double val[N<<2], mul[N<<2];
	void build_(int o, int l, int r) {
		mul[o] = 1;
		if (l == r) val[o] = g[l];
		else {
			int mid = (l + r)>>1;
			build_(o<<1, l, mid), build_(o<<1|1, mid + 1, r);
			val[o] = val[o<<1] + val[o<<1|1];
		}
	}
	void push_down(int o) {
		int ls = o<<1, rs = o<<1|1;
		mul[ls] *= mul[o], mul[rs] *= mul[o];
		val[ls] *= mul[o], val[rs] *= mul[o];
		mul[o] = 1;
	}
	void update_(int o, int l, int r, int x, int y, double k) {
		if (x <= l && r <= y) {
			mul[o] *= k, val[o] *= k;
			return;
		}
		int mid = (l + r)>>1;
		if (fabs(mul[o] - 1.0) > 1e-8) push_down(o);
		if (x <= mid) update_(o<<1, l, mid, x, y, k);
		if (mid < y) update_(o<<1|1, mid + 1, r, x, y, k);
		val[o] = val[o<<1] + val[o<<1|1];
	}
	double query_(int o, int l, int r, int x, int y) {
		if (x > y) return 0;
		if (x <= l && r <= y) return val[o];

		if (fabs(mul[o] - 1.0) > 1e-8) push_down(o);
		int mid = (l + r)>>1;
		double ans = 0;

		if (x <= mid) ans += query_(o<<1, l, mid, x, y);
		if (mid < y) ans += query_(o<<1|1, mid + 1, r, x, y);

		return ans;
	}
} T;

int main() {
	cin>>n>>q;

	rep (i, 1, n) {
		scanf("%d%d", &a[i], &b[i]);
		p[i] = 1.0*a[i]/b[i];
		p[i] = (1.0 - p[i])/p[i];
		g[i] = i == 1 ? p[i] : g[i - 1]*p[i];
	}

	T.build_(1, 1, n);

	while (q--) {
		int id, x, y, c, d;
		scanf("%d%d", &id, &x);
		if (id == 1) {
			scanf("%d%d", &c, &d);
			double w = (double)c/d;
			w = (1 - w)/w;
			T.update_(1, 1, n, x, n, w/p[x]);
			p[x] = w;
		} else {
			scanf("%d", &y);
			double res = T.query_(1, 1, n, x + 1, y)/T.query_(1, 1, n, x, x);
			res = -res*p[x] - p[x];
			printf("%.12Lf\n", 1.0/(1.0 - res));
		}
	}

	return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define rep(i, a, b) for(register int i = a; i <= b; i++)
#define per(i, a, b) for(register int i = a; i >= b; i--)
typedef long long LL;
const LL mod = 1e9 + 7;
const int N = 1e5 + 5;

int n, q, a[N], b[N];
long double g[N], p[N];
struct Tree {
	long double val[N<<2], mul[N<<2];
	void build_(int o, int l, int r) {
		mul[o] = 1;
		if (l == r) val[o] = g[l];
		else {
			int mid = (l + r)>>1;
			build_(o<<1, l, mid), build_(o<<1|1, mid + 1, r);
			val[o] = val[o<<1] + val[o<<1|1];
		}
	}
	void push_down(int o) {
		int ls = o<<1, rs = o<<1|1;
		mul[ls] *= mul[o], mul[rs] *= mul[o];
		val[ls] *= mul[o], val[rs] *= mul[o];
		mul[o] = 1;
	}
	void update_(int o, int l, int r, int x, int y, long double k) {
		if (x <= l && r <= y) {
			mul[o] *= k, val[o] *= k;
			return;
		}
		int mid = (l + r)>>1;
		if (fabs(mul[o] - 1.0) > 1e-8) push_down(o);
		if (x <= mid) update_(o<<1, l, mid, x, y, k);
		if (mid < y) update_(o<<1|1, mid + 1, r, x, y, k);
		val[o] = val[o<<1] + val[o<<1|1];
	}
	long double query_(int o, int l, int r, int x, int y) {
		if (x > y) return 0;
		if (x <= l && r <= y) return val[o];

		if (abs(mul[o] - 1.0) > 1e-8) push_down(o);
		int mid = (l + r)>>1;
		long double ans = 0;

		if (x <= mid) ans += query_(o<<1, l, mid, x, y);
		if (mid < y) ans += query_(o<<1|1, mid + 1, r, x, y);

		return ans;
	}
} T;

int main() {
	cin>>n>>q;

	rep (i, 1, n) {
		scanf("%d%d", &a[i], &b[i]);
		p[i] = 1.0*a[i]/b[i];
		p[i] = (1.0 - p[i])/p[i];
		g[i] = i == 1 ? p[i] : g[i - 1]*p[i];
	}

	T.build_(1, 1, n);

	while (q--) {
		int id, x, y, c, d;
		scanf("%d%d", &id, &x);
		if (id == 1) {
			scanf("%d%d", &c, &d);
			long double w = (long double)c/d;
			w = (1 - w)/w;
			T.update_(1, 1, n, x, n, w/p[x]);
			p[x] = w;
		} else {
			scanf("%d", &y);
			long double res = T.query_(1, 1, n, x + 1, y)/T.query_(1, 1, n, x, x);
			res = -res*p[x] - p[x];
			printf("%.12Lf\n", 1/(1 - res));
		}
	}

	return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define rep(i, a, b) for(register int i = a; i <= b; i++)
#define per(i, a, b) for(register int i = a; i >= b; i--)
typedef long long LL;
const LL mod = 1e9 + 7;
const int N = 1e5 + 5;

int n, q, a[N], b[N];
double g[N], p[N];
struct Tree {
	double val[N<<2], mul[N<<2];
	void clear_() { rep (i, 1, n<<2) mul[i] = 1; }
	void build_(int o, int l, int r) {
		if (l == r) val[o] = g[l];
		else {
			int mid = (l + r)>>1;
			build_(o<<1, l, mid), build_(o<<1|1, mid + 1, r);
			val[o] = val[o<<1] + val[o<<1|1];
		}
	}
	void push_down(int o) {
		int ls = o<<1, rs = o<<1|1;
		mul[ls] *= mul[o], mul[rs] *= mul[o];
		val[ls] *= mul[o], val[rs] *= mul[o];
		mul[o] = 1;
	}
	void update_(int o, int l, int r, int x, int y, double k) {
		if (x <= l && r <= y) {
			mul[o] *= k, val[o] *= k;
			return;
		}
		int mid = (l + r)>>1;
		if (fabs(mul[o] - 1.0) > 1e-8) push_down(o);
		if (x <= mid) update_(o<<1, l, mid, x, y, k);
		if (mid < y) update_(o<<1|1, mid + 1, r, x, y, k);
		val[o] = val[o<<1] + val[o<<1|1];
	}
	double query_(int o, int l, int r, int x, int y) {
		if (x > y) return 0;
		if (x <= l && r <= y) return val[o];

		if (fabs(mul[o] - 1.0) > 1e-8) push_down(o);
		int mid = (l + r)>>1;
		double ans = 0;

		if (x <= mid) ans += query_(o<<1, l, mid, x, y);
		if (mid < y) ans += query_(o<<1|1, mid + 1, r, x, y);

		return ans;
	}
} T;

int main() {
	cin>>n>>q;

	rep (i, 1, n) {
		scanf("%d%d", &a[i], &b[i]);
		p[i] = 1.0*a[i]/b[i];
		p[i] = (1.0 - p[i])/p[i];
		g[i] = i == 1 ? p[i] : g[i - 1]*p[i];
	}

	T.build_(1, 1, n);
	T.clear_();

	while (q--) {
		int id, x, y, c, d;
		scanf("%d%d", &id, &x);
		if (id == 1) {
			scanf("%d%d", &c, &d);
			double w = (double)c/d;
			w = (1 - w)/w;
			T.update_(1, 1, n, x, n, w/p[x]);
			p[x] = w;
		} else {
			scanf("%d", &y);
			double res = T.query_(1, 1, n, x + 1, y)/T.query_(1, 1, n, x, x);
			res = -res*p[x] - p[x];
			printf("%.12f\n", 1.0/(1.0 - res));
		}
	}

	return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define rep(i, a, b) for(register int i = a; i <= b; i++)
#define per(i, a, b) for(register int i = a; i >= b; i--)
typedef long long LL;
const LL mod = 1e9 + 7;
const int N = 1e5 + 5;

int n, q, a[N], b[N];
double g[N], p[N];
struct Tree {
	double val[N<<2], mul[N<<2];
	void build_(int o, int l, int r) {
		mul[o] = 1;
		if (l == r) val[o] = g[l];
		else {
			int mid = (l + r)>>1;
			build_(o<<1, l, mid), build_(o<<1|1, mid + 1, r);
			val[o] = val[o<<1] + val[o<<1|1];
		}
	}
	void push_down(int o) {
		int ls = o<<1, rs = o<<1|1;
		mul[ls] *= mul[o], mul[rs] *= mul[o];
		val[ls] *= mul[o], val[rs] *= mul[o];
		mul[o] = 1;
	}
	void update_(int o, int l, int r, int x, int y, double k) {
		if (x <= l && r <= y) {
			mul[o] *= k, val[o] *= k;
			return;
		}
		int mid = (l + r)>>1;
		if (fabs(mul[o] - 1.0) > 1e-5) push_down(o);
		if (x <= mid) update_(o<<1, l, mid, x, y, k);
		if (mid < y) update_(o<<1|1, mid + 1, r, x, y, k);
		val[o] = val[o<<1] + val[o<<1|1];
	}
	double query_(int o, int l, int r, int x, int y) {
		if (x > y) return 0;
		if (x <= l && r <= y) return val[o];

		if (fabs(mul[o] - 1.0) > 1e-5) push_down(o);
		int mid = (l + r)>>1;
		double ans = 0;

		if (x <= mid) ans += query_(o<<1, l, mid, x, y);
		if (mid < y) ans += query_(o<<1|1, mid + 1, r, x, y);

		return ans;
	}
} T;

int main() {
	cin>>n>>q;

	rep (i, 1, n) {
		scanf("%d%d", &a[i], &b[i]);
		p[i] = 1.0*(b[i] - a[i])/a[i];
		g[i] = i == 1 ? p[i] : g[i - 1]*p[i];
	}

	T.build_(1, 1, n);

	while (q--) {
		int id, x, y, c, d;
		scanf("%d%d", &id, &x);
		if (id == 1) {
			scanf("%d%d", &c, &d);
			double w = 1.0*(d - c)/c;
			T.update_(1, 1, n, x, n, w/p[x]);
			p[x] = w;
		} else {
			scanf("%d", &y);
			double res = T.query_(1, 1, n, x + 1, y), k = T.query_(1, 1, n, x, x);
			res = -res*p[x] - k*p[x];
			printf("%.7f\n", k/(k - res));
		}
	}

	return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define rep(i, a, b) for(register int i = a; i <= b; i++)
#define per(i, a, b) for(register int i = a; i >= b; i--)
typedef long long LL;
const LL mod = 1e9 + 7;
const int N = 1e5 + 5;

int n, q, a[N], b[N];
double g[N], p[N];
struct Tree {
	double val[N<<2], mul[N<<2];
	void build_(int o, int l, int r) {
		mul[o] = 1;
		if (l == r) val[o] = g[l];
		else {
			int mid = (l + r)>>1;
			build_(o<<1, l, mid), build_(o<<1|1, mid + 1, r);
			val[o] = val[o<<1] + val[o<<1|1];
		}
	}
	void push_down(int o) {
		int ls = o<<1, rs = o<<1|1;
		mul[ls] *= mul[o], mul[rs] *= mul[o];
		val[ls] *= mul[o], val[rs] *= mul[o];
		mul[o] = 1;
	}
	void update_(int o, int l, int r, int x, int y, long double k) {
		if (x <= l && r <= y) {
			mul[o] *= k, val[o] *= k;
			return;
		}
		int mid = (l + r)>>1;
		if (fabs(mul[o] - 1.0) > 1e-8) push_down(o);
		if (x <= mid) update_(o<<1, l, mid, x, y, k);
		if (mid < y) update_(o<<1|1, mid + 1, r, x, y, k);
		val[o] = val[o<<1] + val[o<<1|1];
	}
	double query_(int o, int l, int r, int x, int y) {
		if (x > y) return 0;
		if (x <= l && r <= y) return val[o];

		if (fabs(mul[o] - 1.0) > 1e-8) push_down(o);
		int mid = (l + r)>>1;
		double ans = 0;

		if (x <= mid) ans += query_(o<<1, l, mid, x, y);
		if (mid < y) ans += query_(o<<1|1, mid + 1, r, x, y);

		return ans;
	}
} T;

int main() {
	cin>>n>>q;

	rep (i, 1, n) {
		scanf("%d%d", &a[i], &b[i]);
		p[i] = 1.0*a[i]/b[i];
		p[i] = (1.0 - p[i])/p[i];
		g[i] = i == 1 ? p[i] : g[i - 1]*p[i];
	}

	T.build_(1, 1, n);

	while (q--) {
		int id, x, y, c, d;
		scanf("%d%d", &id, &x);
		if (id == 1) {
			scanf("%d%d", &c, &d);
			double w = (double)c/d;
			w = (1 - w)/w;
			T.update_(1, 1, n, x, n, w/p[x]);
			p[x] = w;
		} else {
			scanf("%d", &y);
			double res = T.query_(1, 1, n, x + 1, y)/T.query_(1, 1, n, x, x);
			res = -res*p[x] - p[x];
			printf("%.12f\n", 1.0/(1.0 - res));
		}
	}

	return 0;
}


#include<cstdio>
#define ls p<<1,l,m
#define rs p<<1|1,m+1,r
struct tree{double l,r;}f[400000];
tree operator + (const tree A,const tree B){
	return (tree){A.l*B.l/(1-(1-B.l)*A.r),
	B.r+(1-B.r)*A.r*B.l/(1-(1-B.l)*A.r)};
}
int n,Q,x,y;double k;
int read(){
	char c=getchar();int k=0;for (;c<48||c>57;c=getchar());
	for (;c>47&&c<58;c=getchar()) k=(k<<3)+(k<<1)+c-48;return k;
}
void build(int p,int l,int r){
	if (l==r){double k=(double)read()/read();f[p]=(tree){k,k};return;}
	int m=l+r>>1;build(ls);build(rs);f[p]=f[p<<1]+f[p<<1|1];
}
void change(int p,int l,int r){
	if (l==r){f[p]=(tree){k,k};return;}int m=l+r>>1;
	if (x<=m) change(ls); else change(rs);f[p]=f[p<<1]+f[p<<1|1];
}
tree ask(int p,int l,int r){
	if (x<=l&&r<=y) return f[p];int m=l+r>>1;
	if (y<=m) return ask(ls);if (x>m) return ask(rs);
	return ask(ls)+ask(rs);
}
int main(){
	n=read();Q=read();build(1,1,n);
	for (;Q--;){int w=read();
		if (w==1){x=read();k=(double)read()/read();change(1,1,n);}
		else{x=read();y=read();printf("%.10lf\n",ask(1,1,n).l);}
	}
}


#include<cstdio>
#define ls p<<1,l,m
#define rs p<<1|1,m+1,r
int n,Q,x,y;double k;struct tree{double l,r;}f[400000];
inline tree operator + (const tree A,const tree B){return (tree){A.l*B.l/(1-(1-B.l)*A.r),B.r+(1-B.r)*A.r*B.l/(1-(1-B.l)*A.r)};}
inline int read(){char c=getchar();int k=0;for (;c<48||c>57;c=getchar());for (;c>47&&c<58;c=getchar()) k=(k<<3)+(k<<1)+c-48;return k;}
void build(int p,int l,int r){if (l==r){double k=(double)read()/read();f[p]=(tree){k,k};return;}int m=l+r>>1;build(ls);build(rs);f[p]=f[p<<1]+f[p<<1|1];}
void change(int p,int l,int r){if (l==r){f[p]=(tree){k,k};return;}int m=l+r>>1;if (x<=m) change(ls); else change(rs);f[p]=f[p<<1]+f[p<<1|1];}
tree ask(int p,int l,int r){if (x<=l&&r<=y) return f[p];int m=l+r>>1;if (y<=m) return ask(ls);if (x>m) return ask(rs);return ask(ls)+ask(rs);}
int main(){n=read();Q=read();build(1,1,n);for (;Q--;){int w=read();if (w==1){x=read();k=(double)read()/read();change(1,1,n);}else{x=read();y=read();printf("%.10lf\n",ask(1,1,n).l);}}}


#pragma comment(linker, "/STACK:256000000")

#define _USE_MATH_DEFINES
#define _CRT_SECURE_NO_DEPRECATE
#define _CRT_SECURE_NO_WARNINGS

#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <iomanip>
#include <fstream>
#include <cstring>
#include <cmath>
#include <ctime>
#include <cassert>
#include <memory.h>
#include <string>
#include <vector>
#include <set>
#include <map>
#include <utility>
#include <algorithm>
#include <functional>

using namespace std;

typedef long long int64;
typedef unsigned long long uint64;
typedef pair<int64, int64> pii;

const int INF = (int)(1e9 + 1337);
const int64 LINF = (int64)2e18;
const double EPS = 1e-12;

const int MAXN = 100001;
const int BSIZE = 8;

string s;

int n, q;
double mas[MAXN];
double tri[4 * MAXN];

void build(int u = 1, int tl = 0, int tr = n - 1)
{
	if (tl == tr)
	{
		tri[u] = mas[tl];
		return;
	}
	int mid = (tl + tr) >> 1;
	build(2 * u, tl, mid);
	build(2 * u + 1, mid + 1, tr);
	tri[u] = tri[2 * u] * tri[2 * u + 1] ;
}

void upd(int u, int tl, int tr, int pos, double val)
{
	if (tl == tr)
	{
		tri[u] = val;
		return;
	}
	int mid = (tl + tr) >> 1;
	if (pos > mid)
		upd(2 * u + 1, mid + 1, tr, pos, val);
	else
		upd(2 * u, tl, mid, pos, val);

	tri[u] = tri[2 * u] * tri[2 * u + 1] ;
}

double mul(int u, int tl, int tr, int l, int r)
{
	if (l > r)
		return 1;
	if (tl == l && tr == r)
	{
		return tri[u];
	}
	int mid = (tl + tr) >> 1;
	double t = mul(2 * u, tl, mid, l, min(r, mid));
	double t1 = mul(2 * u + 1, mid + 1, tr, max(mid + 1, l), r);
	return t * t1;
}

void solve()
{
	scanf("%d %d", &n, &q);
	for(int i = 0; i < n; ++i)
	{
		int a, b;
		scanf("%d %d", &a, &b);
		mas[i] = a / (double) b;
	}
	for(int i = 0; i < 4 * MAXN; ++i)
		tri[i] = 1;
	build();
	for(int i = 0; i < q; ++i)
	{
		int t = 1;
		scanf("%d", &t);
		if (t == 1)
		{
			int id, a, b;
			scanf("%d %d %d", &id, &a, &b);
			upd(1, 0, n - 1, id, a / (double) b);
			mas[id] = a / (double) b;
		}
		else
		{
			int l, r;
			scanf("%d %d", &l, &r);
			l--, r--;
			double ans = mul(1, 0, n - 1, l, r);
			ans = ans / (1 - mas[l] + ans);
			printf("%0.10lf\n", ans);
		}
	}
}

int main()
{
#ifdef _MY_DEBUG
	freopen("input.txt", "rt", stdin); freopen("output.txt", "wt", stdout);
#else
#endif

	solve();

	return 0;
}


#pragma comment(linker, "/STACK:256000000")

#define _USE_MATH_DEFINES
#define _CRT_SECURE_NO_DEPRECATE
#define _CRT_SECURE_NO_WARNINGS

#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <iomanip>
#include <fstream>
#include <cstring>
#include <cmath>
#include <ctime>
#include <cassert>
#include <memory.h>
#include <string>
#include <vector>
#include <set>
#include <map>
#include <utility>
#include <algorithm>
#include <functional>

using namespace std;

typedef long long int64;
typedef unsigned long long uint64;
typedef pair<int64, int64> pii;

const int INF = (int)(1e9 + 1337);
const int64 LINF = (int64)2e18;
const double EPS = 1e-12;

const int MAXN = 100001;
const int BSIZE = 8;

string s;

int n, q;
double mas[MAXN];
pair < double, double> tri[4 * MAXN];

pair < double, double> combine(pair < double, double> a, pair < double, double> b)
{
	if(a == make_pair(-1.0, -1.0))
		return b;
	if(b == make_pair(-1.0, -1.0))
		return a;
	pair < double, double> ans;
	ans.first = a.first * b.first / (1 - a.second * (1 - b.first));
	ans.second = b.second + (1 - b.second) * a.second * b.first / (1 - (1 - b.first) * a.second);
	return ans;
}

void build(int u = 1, int tl = 0, int tr = n - 1)
{
	if (tl == tr)
	{
		tri[u] = make_pair(mas[tl], mas[tl]);
		return;
	}
	int mid = (tl + tr) >> 1;
	build(2 * u, tl, mid);
	build(2 * u + 1, mid + 1, tr);
	tri[u] = combine(tri[2 * u], tri[2 * u + 1]);
}

void upd(int u, int tl, int tr, int pos, double val)
{
	if (tl ==tr )
	{
		tri[u] = make_pair(val, val);
		return;
	}
	int mid = (tl + tr) >> 1;
	if (pos > mid)
		upd(2 * u + 1, mid + 1, tr, pos, val);
	else
		upd(2 * u, tl, mid, pos, val);

	tri[u] = combine(tri[2 * u], tri[2 * u + 1]);
}

pair<double, double> mul(int u, int tl, int tr, int l, int r)
{
	if (l > r)
		return make_pair(-1, -1);
	if (tl == l && tr == r)
	{
		return tri[u];
	}
	int mid = (tl + tr) >> 1;
	pair<double, double> t = mul(2 * u, tl, mid, l, min(r, mid));
	pair<double, double> t1 = mul(2 * u + 1, mid + 1, tr, max(mid + 1, l), r);
	return combine(t, t1);
}

void solve()
{
	scanf("%d %d", &n, &q);
	for(int i = 0; i < n; ++i)
	{
		int a, b;
		scanf("%d %d", &a, &b);
		mas[i] = a / (double) b;
	}
	build();
	for(int i = 0; i < q; ++i)
	{
		int t = 1;
		scanf("%d", &t);
		if (t == 1)
		{
			int id, a, b;
			scanf("%d %d %d", &id, &a, &b);
			upd(1, 0, n - 1, id - 1, a / (double) b);
			mas[id] = a / (double) b;
		}
		else
		{
			int l, r;
			scanf("%d %d", &l, &r);
			l--, r--;
			double ans = mul(1, 0, n - 1, l, r).first;
			printf("%0.10lf\n", ans);
		}
	}
}

int main()
{
#ifdef _MY_DEBUG
	freopen("input.txt", "rt", stdin); freopen("output.txt", "wt", stdout);
#else
#endif

	solve();

	return 0;
}


#include<bits/stdc++.h>
#define db double
#define fi first
#define se second
#define MaxN 100010
using namespace std;

db p[MaxN]; int n, q;
struct node {
    double g, f;
} tr[MaxN << 2];

void sum(db &f, db &g, db f1, db f2, db g1, db g2) {
    f = f1 * f2 / (1 - (1 - f2) * (1 - g1));
    g = g1 * g2 / (1 - (1 - f2) * (1 - g1));
}

void BuildTree(int k, int l, int r) {
    if (l == r) {
        tr[k].f = p[l], tr[k].g = 1 - p[l];
        return;
    }
    int mid = l + r >> 1;
    BuildTree(k << 1, l, mid);
    BuildTree(k << 1 | 1, mid + 1, r);
    sum(tr[k].f, tr[k].g, tr[k << 1].f, tr[k << 1 | 1].f, tr[k << 1].g, tr[k << 1 | 1].g);
}

pair<db, db> query(int k, int l, int r, int L, int R) {
    if (L <= l && r <= R)
        return make_pair(tr[k].f, tr[k].g);
    int mid = l + r >> 1;
    pair<db, db> k1, k2;
    k1.fi = k2.fi = k1.se = k2.se = 1;
    if (L <= mid) k1 = query(k << 1, l, mid, L, R);
    if (mid < R) k2 = query(k << 1 | 1, mid + 1, r, L, R);
    db T1, T2;
    sum(T1, T2, k1.fi, k2.fi, k1.se, k2.se);
    return make_pair(T1, T2);
}

void update(int k, int l, int r, int pos, db x) {
    if (l == r) {
        tr[k].f = x, tr[k].g = 1 - x;
        return;
    }
    int mid = l + r >> 1;
    if (pos <= mid) update(k << 1, l, mid, pos, x);
    else update(k << 1 | 1, mid + 1, r, pos, x);
    sum(tr[k].f, tr[k].g, tr[k << 1].f, tr[k << 1 | 1].f, tr[k << 1].g, tr[k << 1 | 1].g);
}

int main() {
	scanf("%d%d", &n, &q);
    for (int i = 1; i <= n; i++) {
    	int a, b;
    	scanf("%d%d", &a, &b);
        p[i] = (db)a / b;
    }
    BuildTree(1, 1, n);
    while (q--) {
        int sit, l, r, pos, a, b; scanf("%d", &sit);
        if (sit & 1) {
        	scanf("%d%d%d", &pos, &a, &b);
            update(1, 1, n, pos, ((db) a / b));
        }
		else {
            scanf("%d%d", &l, &r);
            printf("%.9lf\n", query(1, 1, n, l, r).fi);
        }
    }
    return 0;
}


#include<bits/stdc++.h>
using namespace std ;
#define Next( i, x ) for( register int i = head[x]; i; i = e[i].next )
#define rep( i, s, t ) for( register int i = (s); i <= (t); ++ i )
#define drep( i, s, t ) for( register int i = (t); i >= (s); -- i )
#define re register
#define ls(x) ( x << 1 )
#define rs(x) ( x << 1 | 1 )
int gi() {
	char cc = getchar() ; int cn = 0, flus = 1 ;
	while( cc < '0' || cc > '9' ) {  if( cc == '-' ) flus = - flus ; cc = getchar() ; }
	while( cc >= '0' && cc <= '9' )  cn = cn * 10 + cc - '0', cc = getchar() ;
	return cn * flus ;
}
const int N = 2e5 + 5 ;
const double eps = 1e-9 ;
int n, q ; double p[N] ;
struct Tr {
	double f, g ;
} tr[N << 1] ;
Tr pushup( Tr x, Tr y ) {
	Tr u ;
	u.f = x.f * y.f / ( x.g + y.f - x.g * y.f + eps ) ;
	u.g = x.g * y.g / ( x.g + y.f - x.g * y.f + eps ) ;
	return u ;
}
Tr query( int x, int l, int r, int ql, int qr ) {
	if( ql <= l && r <= qr ) return tr[x] ;
	int mid = ( l + r ) >> 1 ;
	if( mid >= qr ) return query( ls(x), l, mid, ql, qr ) ;
	if( mid < ql ) return query( rs(x), mid + 1, r, ql, qr ) ;
	return pushup( query( ls(x), l, mid, ql, mid ), query( rs(x), mid + 1, r, mid + 1, qr )  );
}
void update( int x, int l, int r, int wh ) {
	if( l == r ) { tr[x].f = p[l], tr[x].g = 1 - p[l] ; return ; }
	int mid = ( l + r ) >> 1 ;
	if( wh <= mid ) update( ls(x), l, mid, wh ) ;
	else update( rs(x), mid + 1, r, wh ) ;
	tr[x] = pushup( tr[ls(x)], tr[rs(x)] ) ;
}
void build( int x, int l, int r ) {
	if( l == r ) { tr[x].f = p[l], tr[x].g = 1 - p[l] ; return ; }
	int mid = ( l + r ) >> 1 ;
	build( ls(x), l, mid ), build( rs(x), mid + 1, r ) ;
	tr[x] = pushup( tr[ls(x)], tr[rs(x)] ) ;
}
signed main()
{
	n = gi(), q = gi() ; int x, y ;
	rep( i, 1, n ) x = gi(), y = gi(), p[i] = ( 1.0 * x ) / ( 1.0 * y ) ;
	build( 1, 1, n ) ;
	rep( i, 1, q ) {
		int opt = gi(), l = gi(), r = gi() ;
		if( opt == 1 ) x = gi(), p[l] = ( 1.0 * r ) / ( 1.0 * x ), update( 1, 1, n, l ) ;
		if( opt == 2 ) printf("%.7lf\n", query( 1, 1, n, l, r ).f ) ;
	}
	return 0 ;
}


#include<bits/stdc++.h>
using namespace std ;
#define Next( i, x ) for( register int i = head[x]; i; i = e[i].next )
#define rep( i, s, t ) for( register int i = (s); i <= (t); ++ i )
#define drep( i, s, t ) for( register int i = (t); i >= (s); -- i )
#define re register
#define ls(x) ( x << 1 )
#define rs(x) ( x << 1 | 1 )
int gi() {
	char cc = getchar() ; int cn = 0, flus = 1 ;
	while( cc < '0' || cc > '9' ) {  if( cc == '-' ) flus = - flus ; cc = getchar() ; }
	while( cc >= '0' && cc <= '9' )  cn = cn * 10 + cc - '0', cc = getchar() ;
	return cn * flus ;
}
const int N = 2e5 + 5 ;
const double eps = 1e-9 ;
int n, q ; double p[N] ;
struct Tr {
	double f, g ;
} tr[N << 1] ;
Tr pushup( Tr x, Tr y ) {
	Tr u ;
	u.f = x.f * y.f / ( x.g + y.f - x.g * y.f + eps ) ;
	u.g = x.g * y.g / ( x.g + y.f - x.g * y.f + eps ) ;
	return u ;
}
Tr query( int x, int l, int r, int ql, int qr ) {
	if( ql <= l && r <= qr ) return tr[x] ;
	int mid = ( l + r ) >> 1 ;
	if( mid >= qr ) return query( ls(x), l, mid, ql, qr ) ;
	if( mid < ql ) return query( rs(x), mid + 1, r, ql, qr ) ;
	return pushup( query( ls(x), l, mid, ql, mid ), query( rs(x), mid + 1, r, mid + 1, qr )  );
}
void update( int x, int l, int r, int wh ) {
	if( l == r ) { tr[x].f = p[l], tr[x].g = 1 - p[l] ; return ; }
	int mid = ( l + r ) >> 1 ;
	if( wh <= mid ) update( ls(x), l, mid, wh ) ;
	else update( rs(x), mid + 1, r, wh ) ;
	tr[x] = pushup( tr[ls(x)], tr[rs(x)] ) ;
}
void build( int x, int l, int r ) {
	if( l == r ) { tr[x].f = p[l], tr[x].g = 1 - p[l] ; return ; }
	int mid = ( l + r ) >> 1 ;
	build( ls(x), l, mid ), build( rs(x), mid + 1, r ) ;
	tr[x] = pushup( tr[ls(x)], tr[rs(x)] ) ;
}
signed main()
{
	n = gi(), q = gi() ; int x, y ;
	rep( i, 1, n ) x = gi(), y = gi(), p[i] = ( 1.0 * x ) / ( 1.0 * y ) ;
	build( 1, 1, n ) ;
	rep( i, 1, q ) {
		int opt = gi(), l = gi(), r = gi() ;
		if( opt == 1 ) x = gi(), p[l] = ( 1.0 * r ) / ( 1.0 * y ), update( 1, 1, n, l ) ;
		if( opt == 2 ) printf("%.7lf\n", query( 1, 1, n, l, r ).f ) ;
	}
	return 0 ;
}


#include <bits/stdc++.h>

#define pb push_back
#define f first
#define s second
#define mp make_pair
#define pp pop_back
#define ll long long
#define ld long double

using namespace std;

const int N = 1234;

const int mod = 1e9 + 7;

int n, q;

ld prob[N];

int main()
{
  ios_base::sync_with_stdio(0);
  #ifdef wws
    freopen("in", "r", stdin);
  #endif
  cin >> n >> q;
  for (int i = 1, a, b;i <= n;i++)
  {
    cin >> a >> b;
    prob[i] = 1.0 * a / b;
  }
  while(q--)
  {
    int type;
    cin >> type;
    if (type == 2)
    {
      int l, r; cin >> l >> r;
      ld ans = 1.0;
      for (int i = l;i <= r;i++) ans *= prob[i];
      for (int i = l + 1;i <= r;i++)
      {
        ld now = (1.0 - prob[i]) * prob[i - 1];
        now = 1.0 / (1.0 - now);
        ans *= now;
      }
      cout << fixed << setprecision(10) << ans << endl;
    }
    else
    {
      int pos, a, b; cin >> pos >> a >> b;
      prob[pos] = 1.0 * a / b;
    }
  }
  return 0;
}


#include <bits/stdc++.h>

#define pb push_back
#define pp pop_back
#define mp make_pair
#define ld long double
#define f first
#define s second
#define ll long long

using namespace std;

const int N = 1e5 + 5;

const int mod = 1e9 + 7;

struct tree
{
  ld l, r;
  bool ok;
  tree()
  {
    l = r = 0.0;
    ok = 0;
  }
} T[N * 4];

int n, q;

tree operator + (tree a, tree b)
{
  if (!a.ok) return b;
  if (!b.ok) return a;
  tree res;
  res.ok = 1;
  res.l = (a.l * b.l) / (1.0 - a.r * (1.0 - b.l));
  res.r = b.r + (a.r * b.l * (1.0 - b.r)) / (1.0 - a.r * (1.0 - b.l));
  return res;
}

void upd(int p, ld x, int v = 1, int tl = 1, int tr = n)
{
  if (tl == tr)
  {
    T[v].l = T[v].r = x;
    T[v].ok = 1;
    return;
  }
  int tm = (tl + tr) / 2;
  if (p <= tm) upd(p, x, v * 2, tl, tm);
  else upd(p, x, v * 2 + 1, tm + 1, tr);
  T[v] = T[v * 2] + T[v * 2 + 1];
}

tree get(int l, int r, int v = 1, int tl = 1, int tr = n)
{
  if (tl > r || tr < l) return tree();
  if (l <= tl && tr <= r) return T[v];
  int tm = (tl + tr) / 2;
  return get(l, r, v * 2, tl, tm) + get(l, r, v * 2 + 1, tm + 1, tr);
}

int main()
{
  ios_base::sync_with_stdio(0);
  #ifdef wws
    freopen("in", "r", stdin);
  #endif
  cin >> n >> q;
  for (int i = 1, a, b;i <= n;i++)
  {
    cin >> a >> b;
    upd(i, 1.0 * a / b);
  }
  while(q--)
  {
    int t;
    cin >> t;
    if (t == 2)
    {
      int l, r;
      cin >> l >> r;
      cout << fixed << setprecision(10) << get(l, r).l << endl;
    }
    else
    {
      int x, a, b;
      cin >> x >> a >> b;
      upd(x, 1.0 * a / b);
    }
  }
  return 0;
}


#include <bits/stdc++.h>

#define FI(i,a,b) for(int i=(a);i<=(b);i++)
#define FD(i,a,b) for(int i=(a);i>=(b);i--)

#define LL long long
#define Ldouble long double
#define PI 3.1415926535897932384626

#define PII pair<int,int>
#define PLL pair<LL,LL>
#define mp make_pair
#define fi first
#define se second

#define eps 1E-4

using namespace std;

int n, q;
double p[100005], g[100005], a[100005];

void init(){
	return;

}

void uu(double nv, int np){
	p[np] = nv;
	return;
}

void qq(int l, int r){
	g[l] = 1;
	a[l] = p[l];
	FI(i, l + 1, r){
		g[i] = 1 / (1 - g[i - 1] * p[i - 1] * (1 - p[i]));
		a[i] = a[i - 1] * p[i] * g[i];
		if(a[i] < eps){
			printf("0\n");
			return;
		}
	}
	printf("%.10lf\n", a[r]);
	return;
}

int main(){
	scanf("%d %d", &n, &q);
	FI(i, 1, n){
		int a, b;
		scanf("%d %d", &a, &b);
		p[i] = (a + .0) / b;
	}
	init();
	while(q--){
		int q, a, b, k;
		scanf("%d %d %d", &q, &a, &b);
		if(q == 1){
			scanf("%d", &k);
			uu((b + .0) / k, a);
		}
		else qq(a, b);
	}
	return 0;
}


#include <bits/stdc++.h>

#define FI(i,a,b) for(int i=(a);i<=(b);i++)
#define FD(i,a,b) for(int i=(a);i>=(b);i--)

#define LL long long
#define Ldouble long double
#define PI 3.1415926535897932384626

#define PII pair<int,int>
#define PLD pair<Ldouble, Ldouble>
#define PLL pair<LL,LL>
#define mp make_pair
#define fi first
#define se second

#define eps 1E-4

using namespace std;

int n, q;

Ldouble p[100005];

PLD merge(PLD x, PLD y){
	Ldouble a = x.fi;
	Ldouble b = x.se;
	Ldouble c = y.fi;
	Ldouble d = y.se;
	return mp(a * c / (1 - (1 - c) * b), d + (1 - d) * b * c / (1 - (1 - c) * b));
}

PLD seg[292929], ans;

void init(int id, int l, int r){
	if(l == r){
		seg[id] = mp(p[l], p[l]);
		return;
	}
	int m = (l + r) >> 1;
	init(id * 2, l, m);
	init(id * 2 + 1, m + 1, r);
	seg[id] = merge(seg[id * 2], seg[id * 2 + 1]);
	return;
}

void upd(int id, int l, int r, int pos){
	if(l == r){
		seg[id] = mp(p[pos], p[pos]);
		return;
	}
	int m = (l + r) >> 1;
	if(pos <= m) upd(id * 2, l, m, pos);
	else upd(id * 2 + 1, m + 1, r, pos);
	seg[id] = merge(seg[id * 2], seg[id * 2 + 1]);
	return;
}

void query(int id, int l, int r, int L, int R){
	if(l > R || L > r) return;
	else if(L <= l && r <= R){
		ans = merge(ans, seg[id]);
		return;
	}
	int m = (l + r) >> 1;
	query(id * 2, l, m, L, R);
	query(id * 2 + 1, m + 1, r, L, R);
	return;
}

int main(){
	scanf("%d %d", &n, &q);
	FI(i, 1, n){
		int a, b;
		scanf("%d %d", &a, &b);
		p[i] = (a + .0) / b;
	}
	init(1, 1, n);
	while(q--){
		int q, a, b, k;
		scanf("%d %d %d", &q, &a, &b);
		if(q == 1){
			scanf("%d", &k);
			p[a] = (b + .0) / k;
			upd(1, 1, n, a);
		}
		else{
			ans = mp(1.0, 0.0);
			query(1, 1, n, a, b);
			printf("%.10lf\n", (double)ans.fi);
		}
	}
	return 0;
}


#include <bits/stdc++.h>

#define FI(i,a,b) for(int i=(a);i<=(b);i++)
#define FD(i,a,b) for(int i=(a);i>=(b);i--)

#define LL long long
#define Ldouble long double
#define PI 3.1415926535897932384626

#define PII pair<int,int>
#define PLL pair<LL,LL>
#define mp make_pair
#define fi first
#define se second

#define eps 1E-4

using namespace std;

int n, q;
double p[100005], g[100005], a[100005];

void init(){
	return;

}

void uu(double nv, int np){
	p[np] = nv;
	return;
}

void qq(int l, int r){
	g[l] = 1;
	a[l] = p[l];

	int tar = min(l + 4000, r);
	FI(i, l + 1, tar){
		g[i] = 1 / (1 - g[i - 1] * p[i - 1] * (1 - p[i]));
		a[i] = a[i - 1] * p[i] * g[i];
		if(a[i] < eps){
			printf("0\n");
			return;
		}
	}
	printf("%.10lf\n", a[tar]);
	return;
}

int main(){
	scanf("%d %d", &n, &q);
	FI(i, 1, n){
		int a, b;
		scanf("%d %d", &a, &b);
		p[i] = (a + .0) / b;
	}
	init();
	while(q--){
		int q, a, b, k;
		scanf("%d %d %d", &q, &a, &b);
		if(q == 1){
			scanf("%d", &k);
			uu((b + .0) / k, a);
		}
		else qq(a, b);
	}
	return 0;
}


#include <bits/stdc++.h>

#define FI(i,a,b) for(int i=(a);i<=(b);i++)
#define FD(i,a,b) for(int i=(a);i>=(b);i--)

#define LL long long
#define Ldouble long double
#define PI 3.1415926535897932384626

#define PII pair<int,int>
#define PLL pair<LL,LL>
#define mp make_pair
#define fi first
#define se second

#define eps 1E-4

using namespace std;

int n, q;
double p[100005], g[100005], a[100005];

void init(){
	return;

}

void uu(double nv, int np){
	p[np] = nv;
	return;
}

void qq(int l, int r){
	g[l] = 1;
	a[l] = p[l];

	int tar = min(l + 1000, r);
	FI(i, l + 1, tar){
		g[i] = 1 / (1 - g[i - 1] * p[i - 1] * (1 - p[i]));
		a[i] = a[i - 1] * p[i] * g[i];
		if(a[i] < eps){
			printf("0\n");
			return;
		}
	}
	printf("%.10lf\n", a[tar]);
	return;
}

int main(){
	scanf("%d %d", &n, &q);
	FI(i, 1, n){
		int a, b;
		scanf("%d %d", &a, &b);
		p[i] = (a + .0) / b;
	}
	init();
	while(q--){
		int q, a, b, k;
		scanf("%d %d %d", &q, &a, &b);
		if(q == 1){
			scanf("%d", &k);
			uu((b + .0) / k, a);
		}
		else qq(a, b);
	}
	return 0;
}


#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
using namespace std;

const int MaxN = (int)1e5 + 7;

struct SegmentType
{
	int l,r; double a,b;
};

int n,q,a[MaxN],b[MaxN];
bool flg;
SegmentType ans,seg[MaxN<<2];

void MakeSeg(int x,int l,int r)
{
	seg[x].l = l; seg[x].r = r;
	if(l==r)
	{
		seg[x].a = 1.0*a[l]/b[l];
		seg[x].b = 1.0 - 1.0*a[l]/b[l];
		return;
	}
	int lc = x<<1, mi = (l+r)>>1;
	MakeSeg(lc,l,mi);
	MakeSeg(lc+1,mi+1,r);
	double t1 = (1-seg[lc+1].a) * (1-seg[lc].b);
	double t2 = (1-seg[lc].b) * (1-seg[lc+1].a);
	seg[x].a = seg[lc].a * seg[lc+1].a / (1-t1);
	seg[x].b = seg[lc+1].b * seg[lc].b / (1-t2);
}

void Update(int x,int id,int a,int b)
{
	if(seg[x].l==seg[x].r)
	{
		seg[x].a = 1.0*a/b;
		seg[x].b = 1.0 - 1.0*a/b;
		return;
	}
	int lc = x<<1;
	if(id<=seg[x<<1].r) Update(x<<1,id,a,b);
	else Update((x<<1)+1,id,a,b);
	double t1 = (1-seg[lc+1].a) * (1-seg[lc].b);
	double t2 = (1-seg[lc].b) * (1-seg[lc+1].a);
	seg[x].a = seg[lc].a * seg[lc+1].a / (1-t1);
	seg[x].b = seg[lc+1].b * seg[lc].b / (1-t2);
}

void Calc(int x,int l,int r)
{
	if(l<=seg[x].l && seg[x].r<=r)
	{
		if(flg)
		{
			ans.a = seg[x].a;
			ans.b = seg[x].b;
			flg = false;
			return;
		}
		double t1,t2;
		t1 = (1-seg[x].a) * (1-ans.b);
		t2 = (1-ans.b) * (1-seg[x].a);
		ans.a = ans.a * seg[x].a / (1-t1);
		ans.b = ans.b * seg[x].b / (1-t2);
		return;
	}
	int lc = x<<1;
	if(l<=seg[lc].r) Calc(lc,l,r);
	if(seg[lc].r<r) Calc(lc+1,l,r);
}

int main()
{

	int i,typ,id,l,r;
	scanf("%d%d",&n,&q);
	for(i=1;i<=n;i++)
		scanf("%d%d",a+i,b+i);
	MakeSeg(1,1,n);

	for(i=1;i<=q;i++)
	{
		scanf("%d",&typ);
		if(typ==1)
		{
			scanf("%d%d%d",&id,&l,&r);
			Update(1,id,l,r);
		}
		else
		{
			scanf("%d%d",&l,&r);
			flg = true;
			Calc(1,l,r);
			printf("%lf\n",ans.a);
		}
	}

	return 0;
}