#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll  n,q;
long double input[100005],mul[100005];
struct po{
    long double ans;
    long double mu;
};
po segmant[400005];
void build (ll  x=1, ll  l=1,ll  r=n)
{
    if(l==r)
    {
        segmant[x].ans=1+(long double)(1.0-input[l]+1e-9)/(input[l]+1e-9);
        segmant[x].mu=(long double)(1.0-input[l])/input[l];return ;
    }
    ll  mid=(l+r)/2;
    build(2*x,l,mid);
    build(2*x+1,mid+1,r);
    segmant[x].ans=segmant[2*x].ans+segmant[2*x].mu*(segmant[2*x+1].ans-1);
    segmant[x].mu=segmant[2*x].mu*segmant[2*x+1].mu;
}
void update(ll  x,ll  ind,long double delta,ll  l,ll  r){
    if(ind<l || ind>r)
        return ;
    if(ind==l && ind==r){
        segmant[x].mu=(1.0-delta)/delta;
        segmant[x].ans=1+(long double)(1.0-delta)/delta;
        return ;}
    update(2*x,ind,delta,l,(r+l)/2);
    update(2*x+1,ind,delta,(l+r)/2+1,r);
    segmant[x].ans=segmant[2*x].ans+segmant[2*x].mu*(segmant[2*x+1].ans-1);
    segmant[x].mu=segmant[2*x].mu*segmant[2*x+1].mu;
}
po re;
po query(ll  x,ll  low,ll  high,ll  l,ll  r){
    if(high<l || low>r)
        return re;
    if(low<=l && high>=r)
        return segmant[x];
    po p1,p2,p;
    p1= query(2*x,low,high,l,(r+l)/2);
   p2= query(2*x+1,low,high,(l+r)/2+1,r);
   p.ans=p1.ans+p1.mu*(p2.ans-1);
   p.mu=p1.mu*p2.mu;
   return p;
}
int   main(){
 // freopen("in","r",stdin);
  //ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
  scanf("%lld%lld",&n,&q);
   mul[0]=1;
   re.ans=1;
   re.mu=1;
   for(ll  i=1;i<=n;i++)
   {
       ll  a,b;
       scanf("%lld%lld",&a,&b);
       input[i]=(long double)a/b;
         //  mul[i]=mul[i-1]*(1-input[i])/input[i];
   }
   build();
   for(ll  i=1;i<=q;i++)
   {
       ll  t;
       scanf("%lld",&t);
       if(t==1){
           ll  u,a,b;
           scanf("%lld%lld%lld",&u,&a,&b);
           update(1,u,(long double)a/b,1,n);
       }
       else
       {ll  l,r;
       scanf("%lld%lld",&l,&r);
       double rr=(double)query(1,l,r,1,n).ans;
       if(fabs(rr)<=1.0)
           while(1);
               if(fabs(rr)<=1.0)
           cout<<0;
       else
       printf("%0.9lf\n",1.0/rr);

       }

   }
   return 0;}


#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll  n,q;
long double input[100005],mul[100005];
long double oo=1e25;
struct po{
    long double ans;
    long double mu;
};
po segmant[400005];
void build (ll  x=1, ll  l=1,ll  r=n)
{
    if(l==r)
    {
        segmant[x].ans=min(oo,1+(long double)(1.0-input[l]+(1e-5))/(input[l]+(1e-5)));
        segmant[x].mu=(long double)(1.0-input[l])/input[l];return ;
    }
    ll  mid=(l+r)/2;
    build(2*x,l,mid);
    build(2*x+1,mid+1,r);
    segmant[x].ans=min(oo,segmant[2*x].ans+segmant[2*x].mu*(segmant[2*x+1].ans-1));
    segmant[x].mu=segmant[2*x].mu*segmant[2*x+1].mu;
}
void update(ll  x,ll  ind,long double delta,ll  l,ll  r){
    if(ind<l || ind>r)
        return ;
    if(ind==l && ind==r){
        segmant[x].mu=(1.0-delta)/delta;
        segmant[x].ans=min(oo,1+(long double)(1.0-delta)/delta);
        return ;}
    update(2*x,ind,delta,l,(r+l)/2);
    update(2*x+1,ind,delta,(l+r)/2+1,r);
    segmant[x].ans=min(oo,segmant[2*x].ans+segmant[2*x].mu*(segmant[2*x+1].ans-1));
    segmant[x].mu=segmant[2*x].mu*segmant[2*x+1].mu;
}
po re;
po query(ll  x,ll  low,ll  high,ll  l,ll  r){
    if(high<l || low>r)
        return re;
    if(low<=l && high>=r)
        return segmant[x];
    po p1,p2,p;
    p1= query(2*x,low,high,l,(r+l)/2);
   p2= query(2*x+1,low,high,(l+r)/2+1,r);
   p.ans=min(oo,p1.ans+p1.mu*(p2.ans-1));
   p.mu=p1.mu*p2.mu;
   return p;
}
int   main(){
  //freopen("in","r",stdin);
  //ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
  scanf("%lld%lld",&n,&q);
   mul[0]=1;
   re.ans=1;
   re.mu=1;
   for(ll  i=1;i<=n;i++)
   {
       ll  a,b;
       scanf("%lld%lld",&a,&b);
       input[i]=(long double)a/b;
         //  mul[i]=mul[i-1]*(1-input[i])/input[i];
   }
   build();
   for(ll  i=1;i<=q;i++)
   {
       ll  t;
       scanf("%lld",&t);
       if(t==1){
           ll  u,a,b;
           scanf("%lld%lld%lld",&u,&a,&b);
           update(1,u,(long double)a/b,1,n);
       }
       else
       {ll  l,r;
       scanf("%lld%lld",&l,&r);
       double rr=(double)query(1,l,r,1,n).ans;

       printf("%0.9lf\n",1.0/rr);

       }

   }
   return 0;}


#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll  n,q;
long double input[100005],mul[100005];
struct po{
    long double ans;
    long double mu;
};
po segmant[400005];
void build (ll  x=1, ll  l=1,ll  r=n)
{
    if(l==r)
    {
        segmant[x].ans=1+(long double)(1.0-input[l]+(1e-5))/(input[l]+(1e-5));
        segmant[x].mu=(long double)(1.0-input[l])/input[l];return ;
    }
    ll  mid=(l+r)/2;
    build(2*x,l,mid);
    build(2*x+1,mid+1,r);
    segmant[x].ans=segmant[2*x].ans+segmant[2*x].mu*(segmant[2*x+1].ans-1);
    segmant[x].mu=segmant[2*x].mu*segmant[2*x+1].mu;
}
void update(ll  x,ll  ind,long double delta,ll  l,ll  r){
    if(ind<l || ind>r)
        return ;
    if(ind==l && ind==r){
        segmant[x].mu=(1.0-delta)/delta;
        segmant[x].ans=1+(long double)(1.0-delta)/delta;
        return ;}
    update(2*x,ind,delta,l,(r+l)/2);
    update(2*x+1,ind,delta,(l+r)/2+1,r);
    segmant[x].ans=segmant[2*x].ans+segmant[2*x].mu*(segmant[2*x+1].ans-1);
    segmant[x].mu=segmant[2*x].mu*segmant[2*x+1].mu;
}
po re;
po query(ll  x,ll  low,ll  high,ll  l,ll  r){
    if(high<l || low>r)
        return re;
    if(low<=l && high>=r)
        return segmant[x];
    po p1,p2,p;
    p1= query(2*x,low,high,l,(r+l)/2);
   p2= query(2*x+1,low,high,(l+r)/2+1,r);
   p.ans=p1.ans+p1.mu*(p2.ans-1);
   p.mu=p1.mu*p2.mu;
   return p;
}
int   main(){
  //freopen("in","r",stdin);
  //ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
  scanf("%lld%lld",&n,&q);
   mul[0]=1;
   re.ans=1;
   re.mu=1;
   for(ll  i=1;i<=n;i++)
   {
       ll  a,b;
       scanf("%lld%lld",&a,&b);
       input[i]=(long double)a/b;
         //  mul[i]=mul[i-1]*(1-input[i])/input[i];
   }
   build();
   for(ll  i=1;i<=q;i++)
   {
       ll  t;
       scanf("%lld",&t);
       if(t==1){
           ll  u,a,b;
           scanf("%lld%lld%lld",&u,&a,&b);
           update(1,u,(long double)a/b,1,n);
       }
       else
       {ll  l,r;
       scanf("%lld%lld",&l,&r);
       double rr=(double)query(1,l,r,1,n).ans;
       if(rr>(1e20))
           cout<<0;
       else
       printf("%0.9lf\n",1.0/rr);

       }

   }
   return 0;}


#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll  n,q;
long double input[100005],mul[100005];
struct po{
    long double ans;
    long double mu;
};
po segmant[400005];
void build (ll  x=1, ll  l=1,ll  r=n)
{
    if(l==r)
    {
        segmant[x].ans=1+(long double)(1.0-input[l]+(1e-5))/(input[l]+(1e-5));
        segmant[x].mu=(long double)(1.0-input[l])/input[l];return ;
    }
    ll  mid=(l+r)/2;
    build(2*x,l,mid);
    build(2*x+1,mid+1,r);
    segmant[x].ans=segmant[2*x].ans+segmant[2*x].mu*(segmant[2*x+1].ans-1);
    segmant[x].mu=segmant[2*x].mu*segmant[2*x+1].mu;
}
void update(ll  x,ll  ind,long double delta,ll  l,ll  r){
    if(ind<l || ind>r)
        return ;
    if(ind==l && ind==r){
        segmant[x].mu=(1.0-delta)/delta;
        segmant[x].ans=1+(long double)(1.0-delta)/delta;
        return ;}
    update(2*x,ind,delta,l,(r+l)/2);
    update(2*x+1,ind,delta,(l+r)/2+1,r);
    segmant[x].ans=segmant[2*x].ans+segmant[2*x].mu*(segmant[2*x+1].ans-1);
    segmant[x].mu=segmant[2*x].mu*segmant[2*x+1].mu;
}
po re;
po query(ll  x,ll  low,ll  high,ll  l,ll  r){
    if(high<l || low>r)
        return re;
    if(low<=l && high>=r)
        return segmant[x];
    po p1,p2,p;
    p1= query(2*x,low,high,l,(r+l)/2);
   p2= query(2*x+1,low,high,(l+r)/2+1,r);
   p.ans=p1.ans+p1.mu*(p2.ans-1);
   p.mu=p1.mu*p2.mu;
   return p;
}
int   main(){
  //freopen("in","r",stdin);
  //ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
  scanf("%lld%lld",&n,&q);
   mul[0]=1;
   re.ans=1;
   re.mu=1;
   for(ll  i=1;i<=n;i++)
   {
       ll  a,b;
       scanf("%lld%lld",&a,&b);
       input[i]=(long double)a/b;
         //  mul[i]=mul[i-1]*(1-input[i])/input[i];
   }
   build();
   for(ll  i=1;i<=q;i++)
   {
       ll  t;
       scanf("%lld",&t);
       if(t==1){
           ll  u,a,b;
           scanf("%lld%lld%lld",&u,&a,&b);
           update(1,u,(long double)a/b,1,n);
       }
       else
       {ll  l,r;
       scanf("%lld%lld",&l,&r);
       double rr=(double)query(1,l,r,1,n).ans;
       if(fabs(rr)<=1.0)
           while(1);
               if(fabs(rr)<=1.0)
           cout<<0;
       else
       printf("%0.9lf\n",1.0/rr);

       }

   }
   return 0;}


#include <bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define fz(i,a,b) for(int i=a;i<=b;i++)
#define fd(i,a,b) for(int i=a;i>=b;i--)
#define ffe(it,v) for(__typeof(v.begin()) it=v.begin();it!=v.end();it++)
#define fill0(a) memset(a,0,sizeof(a))
#define fill1(a) memset(a,-1,sizeof(a))
#define fillbig(a) memset(a,63,sizeof(a))
#define pb push_back
#define mp make_pair
typedef pair<int,int> pii;
typedef long long ll;
struct node{
	int l,r;double v,w;
} s[100005<<2];
void build(int k,int l,int r){
	s[k].l=l;s[k].r=r;if(l==r) return;
	int mid=(l+r)>>1;build(k<<1,l,mid);build(k<<1|1,mid+1,r);
}
void modify(int k,int x,double v){
	if(s[k].l==s[k].r){s[k].v=s[k].w=(1-v)/v;return;}
	int mid=(s[k].l+s[k].r)>>1;
	if(x<=mid) modify(k<<1,x,v);
	else modify(k<<1|1,x,v);
	s[k].v=s[k<<1].v*s[k<<1|1].v;
	s[k].w=s[k<<1].w+s[k<<1].v*s[k<<1|1].w;
}
double query(int k,int l,int r){
	if(l<=s[k].l&&s[k].r<=r) return s[k].v;
	int mid=(s[k].l+s[k].r)>>1;
	if(r<=mid) return query(k<<1,l,r);
	else if(l>mid) return query(k<<1|1,l,r);
	else return query(k<<1,l,mid)*query(k<<1|1,mid+1,r);
}
double queryw(int k,int l,int r){
	if(l<=s[k].l&&s[k].r<=r) return s[k].w;
	int mid=(s[k].l+s[k].r)>>1;
	if(r<=mid) return queryw(k<<1,l,r);
	else if(l>mid) return queryw(k<<1|1,l,r);
	else return queryw(k<<1,l,mid)+query(k<<1,l,mid)*queryw(k<<1|1,mid+1,r);
}
int n,q;
int main(){
	scanf("%d%d",&n,&q);build(1,1,n);
	for(int i=1;i<=n;i++){
		int a,b;scanf("%d%d",&a,&b);modify(1,i,1.0*a/b);
	}
	for(int i=1;i<=q;i++){
		int opt;scanf("%d",&opt);
		if(opt==1){
			int x,a,b;scanf("%d%d%d",&x,&a,&b);
			modify(1,x,1.0*a/b);
		} else {
			int l,r;scanf("%d%d",&l,&r);
			double mul=queryw(1,l,r);
			printf("%.16lf\n",1.0/(1.0+mul));
		}
	}
	return 0;
}


#include<cstdio>
#include<iostream>
using namespace std;
const int N=1e5+5;
double p[N],A[N*3],B[N*3],aa,bb;
inline void build(int x,int l,int r) {
	if(l==r) {
		A[x]=(1-p[l])/p[l];
		B[x]=A[x];
		return;
	}
	int lc=x<<1,rc=lc+1,mid=(l+r)>>1;
	build(lc,l,mid);
	build(rc,mid+1,r);
	A[x]=A[lc]*A[rc];
	B[x]=B[lc]+B[rc]*A[lc];
}
inline void modify(int x,int l,int r,int pos) {
	if(l==r) {
		A[x]=(1-p[l])/p[l];
		B[x]=A[x];
		return;
	}
	int lc=x<<1,rc=lc+1,mid=(l+r)>>1;
	if(pos<=mid) modify(lc,l,mid,pos);
	else modify(rc,mid+1,r,pos);
	A[x]=A[lc]*A[rc];
	B[x]=B[lc]+B[rc]*A[lc];
}
inline void query(int x,int l,int r,int a,int b) {
	if(l==a&&r==b) {
		bb+=aa*B[x];
		aa*=A[x];
		return;
	}
	int lc=x<<1,rc=lc+1,mid=(l+r)>>1;
	if(b<=mid) query(lc,l,mid,a,b);
	else if(a>mid) query(rc,mid+1,r,a,b);
	else query(lc,l,mid,a,mid),query(rc,mid+1,r,mid+1,b);
}
int main() {
	int n,q,a,b;
	scanf("%d%d",&n,&q);
	for(int i=1;i<=n;i++) {
		scanf("%d%d",&a,&b);
		p[i]=a/(b*1.0);
	}
	build(1,1,n);
	int ope,l,r,pos;
	while(q--) {
		scanf("%d",&ope);
		if(ope==1) {
			scanf("%d%d%d",&pos,&a,&b);
			p[pos]=a/(b*1.0);
			modify(1,1,n,pos);
		} else {
			scanf("%d%d",&l,&r);
			aa=1;bb=0;
			query(1,1,n,l,r);
			double ans;
			if(bb<=1e15) ans=1/(1+bb);
			else ans=0;
			printf("%.10lf\n",ans);
		}
	}
	return 0;
}


#include<cstdio>
#include<iostream>
using namespace std;
typedef long double LD;
const int N=1e5+5;
LD p[N],A[N*3],B[N*3],aa,bb;
inline void build(int x,int l,int r) {
	if(l==r) {
		A[x]=(1-p[l])/p[l];
		B[x]=A[x];
		return;
	}
	int lc=x<<1,rc=lc+1,mid=(l+r)>>1;
	build(lc,l,mid);
	build(rc,mid+1,r);
	A[x]=A[lc]*A[rc];
	B[x]=B[lc]+B[rc]*A[lc];
}
inline void modify(int x,int l,int r,int pos) {
	if(l==r) {
		A[x]=(1-p[l])/p[l];
		B[x]=A[x];
		return;
	}
	int lc=x<<1,rc=lc+1,mid=(l+r)>>1;
	if(pos<=mid) modify(lc,l,mid,pos);
	else modify(rc,mid+1,r,pos);
	A[x]=A[lc]*A[rc];
	B[x]=B[lc]+B[rc]*A[lc];
}
inline void query(int x,int l,int r,int a,int b) {
	if(l==a&&r==b) {
		bb+=aa*B[x];
		aa*=A[x];
		return;
	}
	int lc=x<<1,rc=lc+1,mid=(l+r)>>1;
	if(b<=mid) query(lc,l,mid,a,b);
	else if(a>mid) query(rc,mid+1,r,a,b);
	else query(lc,l,mid,a,mid),query(rc,mid+1,r,mid+1,b);
}
int main() {
	int n,q,a,b;
	scanf("%d%d",&n,&q);
	for(int i=1;i<=n;i++) {
		scanf("%d%d",&a,&b);
		p[i]=a/(b*1.0);
	}
	build(1,1,n);
	int ope,l,r,pos;
	while(q--) {
		scanf("%d",&ope);
		if(ope==1) {
			scanf("%d%d%d",&pos,&a,&b);
			p[pos]=a/(b*1.0);
			modify(1,1,n,pos);
		} else {
			scanf("%d%d",&l,&r);
			aa=1;bb=0;
			query(1,1,n,l,r);
			printf("%.10Lf\n",1/(1+bb));
		}
	}
	return 0;
}


#include<cstdio>
#include<iostream>
using namespace std;
const int N=1e5+5;
double p[N],A[N*3],B[N*3],aa,bb;
inline void build(int x,int l,int r) {
	if(l==r) {
		A[x]=(1-p[l])/p[l];
		B[x]=A[x];
		return;
	}
	int lc=x<<1,rc=lc+1,mid=(l+r)>>1;
	build(lc,l,mid);
	build(rc,mid+1,r);
	A[x]=A[lc]*A[rc];
	B[x]=B[lc]+B[rc]*A[lc];
}
inline void modify(int x,int l,int r,int pos) {
	if(l==r) {
		A[x]=(1-p[l])/p[l];
		B[x]=A[x];
		return;
	}
	int lc=x<<1,rc=lc+1,mid=(l+r)>>1;
	if(pos<=mid) modify(lc,l,mid,pos);
	else modify(rc,mid+1,r,pos);
	A[x]=A[lc]*A[rc];
	B[x]=B[lc]+B[rc]*A[lc];
}
inline void query(int x,int l,int r,int a,int b) {
	if(l==a&&r==b) {
		bb+=aa*B[x];
		aa*=A[x];
		return;
	}
	int lc=x<<1,rc=lc+1,mid=(l+r)>>1;
	if(b<=mid) query(lc,l,mid,a,b);
	else if(a>mid) query(rc,mid+1,r,a,b);
	else query(lc,l,mid,a,mid),query(rc,mid+1,r,mid+1,b);
}
int main() {
	int n,q,a,b;
	scanf("%d%d",&n,&q);
	for(int i=1;i<=n;i++) {
		scanf("%d%d",&a,&b);
		p[i]=a/(b*1.0);
	}
	build(1,1,n);
	int ope,l,r,pos;
	while(q--) {
		scanf("%d",&ope);
		if(ope==1) {
			scanf("%d%d%d",&pos,&a,&b);
			p[pos]=a/(b*1.0);
			modify(1,1,n,pos);
		} else {
			scanf("%d%d",&l,&r);
			aa=1;bb=0;
			query(1,1,n,l,r);
			double ans=1/(1+bb);
			printf("%.10lf\n",ans);
		}
	}
	return 0;
}


#include<cstdio>
#include<iostream>
using namespace std;
const int N=1e5+100;
#define ll o<<1
#define rr o<<1|1
#define mid (l+r)/2
double ff[N<<2],gg[N<<2];
double aa[N],bb[N];

double fun(double f1,double g1,double f2,double g2){
    return f1*f2/(1-(1-f2)*g1);
}
double gun(double f1,double g1,double f2,double g2){
    return g2+(1-g2)*g1*f2/(1-(1-g2)*g1);
}

void up(int o){
    ff[o]=fun(ff[ll],gg[ll],ff[rr],gg[rr]);
    gg[o]=gun(ff[ll],gg[ll],ff[rr],gg[rr]);
}

void build(int l,int r,int o){
    if(l==r){
        ff[o]=gg[o]=aa[l]/bb[l];
        return ;
    }
    build(l,mid,ll);
    build(mid+1,r,rr);
    up(o);
}

int L,R;double V;
void update(int l,int r,int o,int x){
    if(l==r){
        ff[o]=gg[o]=V;return ;
    }
    if(x<=mid)update(l,mid,ll,x);
    else update(mid+1,r,rr,x);
    up(o);
}

double f1,g1;
int fg;
void query(int l,int r,int o){
    if(L<=l&&r<=R){
        if(!fg){
            fg=1;
            f1=ff[o],g1=gg[o];
            return ;
        }
        double f2=fun(f1,g1,ff[o],gg[o]);
        double g2=gun(f1,g1,ff[o],gg[o]);
        f1=f2,g1=g2;
        return ;
    }
    if(L<=mid)query(l,mid,ll);
    if(R>mid)query(mid+1,r,rr);
}

int main(){
    #ifdef DouBi
    freopen("in.cpp","r",stdin);
    #endif // DouBi
    int n,q;
    while(scanf("%d%d",&n,&q)!=EOF){
        for(int i=0;i<n;i++){
            scanf("%lf%lf",&aa[i],&bb[i]);
        }
        build(0,n-1,1);
        for(int i=0;i<q;i++){
            int op,id,l,r;scanf("%d",&op);
            if(op==1){
                scanf("%d%d%d",&id,&l,&r);
                V=(double)l/r;
                update(0,n-1,1,id-1);
            }
            else {
                scanf("%d%d",&L,&R);
                L--,R--;
                fg=0;
                query(0,n-1,1);
                printf("%.10lf\n",f1);
            }
        }
    }
    return 0;
}


#include<cstdio>
#include<iostream>
using namespace std;
const int N=1e5+100;
#define ll o<<1
#define rr o<<1|1
#define mid (l+r)/2
double ff[N<<2],gg[N<<2];
double aa[N],bb[N];

double fun(double f1,double g1,double f2,double g2){
    return f1*f2/(1-(1-f2)*g1);
}
double gun(double f1,double g1,double f2,double g2){
    return g2+(1-g2)*g1*f2/(1-(1-f2)*g1);
}

void up(int o){
    ff[o]=fun(ff[ll],gg[ll],ff[rr],gg[rr]);
    gg[o]=gun(ff[ll],gg[ll],ff[rr],gg[rr]);
}

void build(int l,int r,int o){
    if(l==r){
        ff[o]=gg[o]=aa[l]/bb[l];
        return ;
    }
    build(l,mid,ll);
    build(mid+1,r,rr);
    up(o);
}

int L,R;double V;
void update(int l,int r,int o,int x){
    if(l==r){
        ff[o]=gg[o]=V;return ;
    }
    if(x<=mid)update(l,mid,ll,x);
    else update(mid+1,r,rr,x);
    up(o);
}

double f1,g1;
int fg;
void query(int l,int r,int o){
    if(L<=l&&r<=R){
        if(!fg){
            fg=1;
            f1=ff[o],g1=gg[o];
            return ;
        }
        double f2=fun(f1,g1,ff[o],gg[o]);
        double g2=gun(f1,g1,ff[o],gg[o]);
        f1=f2,g1=g2;
        return ;
    }
    if(L<=mid)query(l,mid,ll);
    if(R>mid)query(mid+1,r,rr);
}

int main(){
    #ifdef DouBi
    freopen("in.cpp","r",stdin);
    #endif // DouBi
    int n,q;
    while(scanf("%d%d",&n,&q)!=EOF){
        for(int i=0;i<n;i++){
            scanf("%lf%lf",&aa[i],&bb[i]);
        }
        build(0,n-1,1);
        for(int i=0;i<q;i++){
            int op,id,l,r;scanf("%d",&op);
            if(op==1){
                scanf("%d%d%d",&id,&l,&r);
                V=(double)l/r;
                update(0,n-1,1,id-1);
            }
            else {
                scanf("%d%d",&L,&R);
                L--,R--;
                fg=0;
                query(0,n-1,1);
                printf("%.10lf\n",f1);
            }
        }
    }
    return 0;
}


#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>

using namespace std;

const int NMAX = 270000;

struct Node
{
	double LL, LR, RL, RR;
};

int N, Q;
int L;
Node tree[NMAX];

inline Node merge(const Node &l, const Node &r)
{
	double t1, t2;
	t1 = l.LL + l.LR * r.LL * l.RL * 1 / (1 - l.RR * r.LL);
	t2 = r.RR + r.RL * l.RR * r.LR * 1 / (1 - r.LL * l.RR);
	return (Node){t1, 1 - t1, 1 - t2, t2};
}

void buildTree()
{
	int pos;
	for(pos = L - 1;pos;pos -= 1)
		tree[pos] = merge(tree[2 * pos], tree[2 * pos + 1]);
}

void edit(int pos, double v)
{
	pos += L - 1;
	tree[pos] = (Node){1 - v, v, 1 - v, v};
	for(pos >>= 1;pos;pos >>= 1)
		tree[pos] = merge(tree[2 * pos], tree[2 * pos + 1]);
}

Node query(int pos, int l, int r, int p, int q)
{
	int mid = (l + r)>>1;
	Node resl, resr;
	if(l == p && r == q)
		return tree[pos];
	if(p <= mid)
		resl = query(2 * pos, l, mid, p, min(q, mid));
	if(q > mid)
		resr = query(2 * pos + 1, mid + 1, r, max(p, mid + 1), q);
	if(p <= mid && q > mid)
		return merge(resl, resr);
	else if(p <= mid)
		return resl;
	return resr;
}

int main()
{
	int i, t, pos, x, y;
	scanf("%d %d", &N, &Q);
	for(L = 1;L < N;L <<= 1);
	for(i = 1;i <= N;i += 1)
	{
		scanf("%d %d", &x, &y);
		tree[L + i - 1] = (Node){1 - (double)x / y, (double)x / y, 1 - (double)x / y, (double)x / y};
	}
	for(;i <= L;i += 1)
		tree[L + i - 1] = (Node){0.5, 0.5, 0.5, 0.5};
	buildTree();
	for(i = 1;i <= Q;i += 1)
	{
		scanf("%d", &t);
		if(t == 1)
		{
			scanf("%d %d %d", &pos, &x, &y);
			edit(pos, (double)x / y);
		}
		else
		{
			scanf("%d %d", &x, &y);
			printf("%.10f\n", query(1, 1, L, x, y).LR);
		}
	}
	exit(0);
}


#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>

using namespace std;

const int NMAX = 270000;

struct Node
{
	double LL, LR, RL, RR;
};

int N, Q;
int L;
Node tree[NMAX];

Node merge(const Node &l, const Node &r)
{
	double t1, t2;
	t1 = l.LL + l.LR * r.LL * l.RL * 1 / (1 - l.RR * r.LL);
	t2 = r.RR + r.RL * l.RR * r.LR * 1 / (1 - r.LL * l.RR);
	return (Node){t1, 1 - t1, 1 - t2, t2};
}

void buildTree()
{
	int pos;
	for(pos = L - 1;pos;pos -= 1)
		tree[pos] = merge(tree[2 * pos], tree[2 * pos + 1]);
}

void edit(int pos, double v)
{
	pos += L - 1;
	tree[pos] = (Node){1 - v, v, 1 - v, v};
	for(pos >>= 1;pos;pos >>= 1)
		tree[pos] = merge(tree[2 * pos], tree[2 * pos + 1]);
}

Node query(int pos, int l, int r, int p, int q)
{
	int mid = (l + r)>>1;
	Node resl, resr;
	if(l == p && r == q)
		return tree[pos];
	if(p <= mid)
		resl = query(2 * pos, l, mid, p, min(q, mid));
	if(q > mid)
		resr = query(2 * pos + 1, mid + 1, r, max(p, mid + 1), q);
	if(p <= mid && q > mid)
		return merge(resl, resr);
	else if(p <= mid)
		return resl;
	return resr;
}

int main()
{
	int i, t, pos, x, y;
	scanf("%d %d", &N, &Q);
	for(L = 1;L < N;L <<= 1);
	for(i = 1;i <= N;i += 1)
	{
		scanf("%d %d", &x, &y);
		tree[L + i - 1] = (Node){1 - (double)x / y, (double)x / y, 1 - (double)x / y, (double)x / y};
	}
	for(;i <= L;i += 1)
		tree[L + i - 1] = (Node){0.5, 0.5, 0.5, 0.5};
	buildTree();
	for(i = 1;i <= Q;i += 1)
	{
		scanf("%d", &t);
		if(t == 1)
		{
			scanf("%d %d %d", &pos, &x, &y);
			edit(pos, (double)x / y);
		}
		else
		{
			scanf("%d %d", &x, &y);
			printf("%.10f\n", query(1, 1, L, x, y).LR);
		}
	}
	exit(0);
}


#include <bits/stdc++.h>

using namespace std;

const int N = 5;
const int M = (int)1e5 + 10;

class Matrix
{
private:
    int n, m;
    double a[N][N];

public:
    Matrix(int n, int m) : n(n), m(m) {
        for(int i = 0; i < n; ++i)
            for (int j = 0; j < m; ++j)
                a[i][j] = 0;
    }

    Matrix() {Matrix(0, 0);}

    void updateElement(int i, int j, double d){
        a[i][j] = d;
    }

    void addToElement(int i, int j, double d){
        a[i][j] += d;
    }

    double get(int i, int j){
        return a[i][j];
    }

    Matrix operator * (const Matrix &b){
        Matrix res(n, b.m);
        for (int i = 0; i < n; ++i)
            for (int j = 0; j < b.m; ++j)
                for (int k = 0; k < m; ++k)
                    res.addToElement(i, j, a[i][k] * b.a[k][j]);
        return res;
    }
};

Matrix fractionToMatrix(int a, int b){
    Matrix res(2, 1);
    res.updateElement(0, 0, a);
    res.updateElement(1, 0, b);
    return res;
}

Matrix createTransformMatrix(double a, double b){
    Matrix res(2, 2);
    res.updateElement(0, 0, 1);
    res.updateElement(0, 1, 0);
    res.updateElement(1, 0, 1);
    res.updateElement(1, 1, b / a - 1);
    return res;
}

Matrix createE(int n, int m){
    Matrix res(n, m);
    for (int i = 0; i < n && i < m; ++i)
        res.updateElement(i, i, 1);
    return res;
}

class SegmentsTree
{
private:
    int l, r, sz;
    Matrix mult;
    SegmentsTree *left, *right;

public:
    SegmentsTree(int l, int r) : l(l), r(r) {
        mult = createE(2, 2);
        left = right = NULL;
        sz = 0;
        if (l == r) sz = 1;
        if (l < r){
            left = new SegmentsTree(l, (l + r) / 2);
            right = new SegmentsTree((l + r) / 2 + 1, r);
            sz = left->sz + right->sz;
        }
    }

    void modify(int pos, int a, int b){
        if (l == pos && r == pos){
            mult = createTransformMatrix(a, b);
        } else {
            if (pos <= left->r) left->modify(pos, a, b);
            if (pos >= right->l) right->modify(pos, a, b);
            mult = left->mult * right->mult;
        }
    }

    Matrix getTransform(int _l, int _r){
        if (_l == l && r == _r) return mult;
        Matrix res = createE(2, 2);
        if (_l <= left->r) res = res * left->getTransform(_l, min(left->r, _r));
        if (_r >= right->l) res = res * right->getTransform(max(right->l, _l), _r);
        return res;
    }
};

Matrix p[M];
SegmentsTree *t;

int n, q;

int main()
{
    ios_base::sync_with_stdio(false);
    cin >> n >> q;
    t = new SegmentsTree(0, n);
    for (int i = 1; i <= n; ++i){
        int a, b; cin >> a >> b;
        p[i] = fractionToMatrix(a, b);
        t->modify(i, a, b);
    }

    Matrix cur = t->getTransform(0, 1);

    cout << setprecision(6) << fixed;

    while (q--){
        int tp; cin >> tp;
        if (tp == 1){
            int pos, a, b; cin >> pos >> a >> b;
            t->modify(pos, a, b);
            p[pos] = fractionToMatrix(a, b);
        } else {
            int l, r; cin >> l >> r;
            Matrix transformMatrix = t->getTransform(l, r - 1);
            Matrix res = transformMatrix * p[r];
            double resd = res.get(0, 0) / res.get(1, 0);
            if (resd != resd) cout << 0 << endl;
            else cout << resd << endl;
        }
    }
    return 0;
}


#include <bits/stdc++.h>

using namespace std;

const int N = 5;
const int M = (int)1e5 + 10;

class Matrix
{
private:
    int n, m;
    double a[N][N];

public:
    Matrix(int n, int m) : n(n), m(m) {
        for(int i = 0; i < n; ++i)
            for (int j = 0; j < m; ++j)
                a[i][j] = 0;
    }

    Matrix() {Matrix(0, 0);}

    void updateElement(int i, int j, double d){
        a[i][j] = d;
    }

    void addToElement(int i, int j, double d){
        a[i][j] += d;
    }

    double get(int i, int j){
        return a[i][j];
    }

    Matrix operator * (const Matrix &b){
        Matrix res(n, b.m);
        for (int i = 0; i < n; ++i)
            for (int j = 0; j < b.m; ++j)
                for (int k = 0; k < m; ++k)
                    res.addToElement(i, j, a[i][k] * b.a[k][j]);
        return res;
    }
};

Matrix fractionToMatrix(int a, int b){
    Matrix res(2, 1);
    res.updateElement(0, 0, a);
    res.updateElement(1, 0, b);
    return res;
}

Matrix createTransformMatrix(double a, double b){
    Matrix res(2, 2);
    res.updateElement(0, 0, 1);
    res.updateElement(0, 1, 0);
    res.updateElement(1, 0, 1);
    res.updateElement(1, 1, b / a - 1);
    return res;
}

Matrix createE(int n, int m){
    Matrix res(n, m);
    for (int i = 0; i < n && i < m; ++i)
        res.updateElement(i, i, 1);
    return res;
}

class SegmentsTree
{
private:
    int l, r, sz;
    Matrix mult;
    SegmentsTree *left, *right;

public:
    SegmentsTree(int l, int r) : l(l), r(r) {
        mult = createE(2, 2);
        left = right = NULL;
        sz = 0;
        if (l == r) sz = 1;
        if (l < r){
            left = new SegmentsTree(l, (l + r) / 2);
            right = new SegmentsTree((l + r) / 2 + 1, r);
            sz = left->sz + right->sz;
        }
    }

    void modify(int pos, int a, int b){
        if (l == pos && r == pos){
            mult = createTransformMatrix(a, b);
        } else {
            if (pos <= left->r) left->modify(pos, a, b);
            if (pos >= right->l) right->modify(pos, a, b);
            mult = left->mult * right->mult;
        }
    }

    Matrix getTransform(int _l, int _r){
        if (_l == l && r == _r) return mult;
        Matrix res = createE(2, 2);
        if (_l <= left->r) res = res * left->getTransform(_l, min(left->r, _r));
        if (_r >= right->l) res = res * right->getTransform(max(right->l, _l), _r);
        return res;
    }
};

Matrix p[M];
SegmentsTree *t;

int n, q;

int main()
{
    ios_base::sync_with_stdio(false);
    cin >> n >> q;
    t = new SegmentsTree(0, n);
    for (int i = 1; i <= n; ++i){
        int a, b; cin >> a >> b;
        p[i] = fractionToMatrix(a, b);
        t->modify(i, a, b);
    }

    Matrix cur = t->getTransform(0, 1);

    cout << setprecision(6) << fixed;

    while (q--){
        int tp; cin >> tp;
        if (tp == 1){
            int pos, a, b; cin >> pos >> a >> b;
            t->modify(pos, a, b);
            p[pos] = fractionToMatrix(a, b);
        } else {
            int l, r; cin >> l >> r;
            Matrix transformMatrix = t->getTransform(l, r - 1);
            Matrix res = transformMatrix * p[r];
            cout << res.get(0, 0) / res.get(1, 0) << endl;
        }
    }
    return 0;
}


#include <vector>
#include <list>
#include <map>
#include <set>
#include <deque>
#include <queue>
#include <stack>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cctype>
#include <string>
#include <cstring>
#include <ctime>
#include <cassert>
#include <string.h>
//#include <unordered_set>
//#include <unordered_map>
//#include <bits/stdc++.h>

#define MP(A,B) make_pair(A,B)
#define PB(A) push_back(A)
#define SIZE(A) ((int)A.size())
#define LEN(A) ((int)A.length())
#define FOR(i,a,b) for(int i=(a);i<(b);++i)
#define fi first
#define se second

using namespace std;

template<typename T>inline bool upmin(T &x,T y) { return y<x?x=y,1:0; }
template<typename T>inline bool upmax(T &x,T y) { return x<y?x=y,1:0; }

typedef long long ll;
typedef unsigned long long ull;
typedef long double lod;
typedef pair<lod,lod> PR;
typedef vector<int> VI;

const lod eps=1e-11;
const lod pi=acos(-1);
const ll oo=1<<30;
const ll loo=1ll<<62;
const int mods=1e9+7;
const int MAXN=100005;
const int INF=0x3f3f3f3f;//1061109567
/*--------------------------------------------------------------------*/
inline int read()
{
	int f=1,x=0; char c=getchar();
	while (c<'0'||c>'9') { if (c=='-') f=-1; c=getchar(); }
	while (c>='0'&&c<='9') { x=(x<<3)+(x<<1)+(c^48); c=getchar(); }
	return x*f;
}
PR f[MAXN<<2];
PR operator +(PR x,PR y) { return MP(x.fi*y.fi,x.se+y.se*x.fi); }
void update(int x,int l,int r,int y,lod z)
{
	if (l==r) { f[x]=MP((1-z)/z,(1-z)/z); return; }
	int mid=(l+r)>>1;
	if (y<=mid) update(x<<1,l,mid,y,z);
	else update(x<<1|1,mid+1,r,y,z);
	f[x]=f[x<<1]+f[x<<1|1];
}
PR query(int x,int l,int r,int L,int R)
{
	if (l>=L&&r<=R) return f[x];
	int mid=(l+r)>>1;
	if (R<=mid) return query(x<<1,l,mid,L,R);
	else if (L>mid) return query(x<<1|1,mid+1,r,L,R);
	else return query(x<<1,l,mid,L,mid)+query(x<<1|1,mid+1,r,mid+1,R);
}
signed main()
{
	int n=read(),Case=read();
	for (int i=1,x,y;i<=n;i++) x=read(),y=read(),update(1,1,n,i,1.0*x/y);
	while (Case--)
	{
		int opt=read(),x=read(),y=read(),z;
		if (opt==1) z=read(),update(1,1,n,x,1.0*y/z);
		else printf("%.10lf\n",(double)(1.0/(query(1,1,n,x,y).se+1)));
	}
	return 0;
}


//satyaki3794
#include <bits/stdc++.h>
#define ff first
#define ss second
#define pb push_back
#define MOD (1000000007LL)
#define LEFT(n) (2*(n))
#define RIGHT(n) (2*(n)+1)

using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> ii;
typedef pair<int, ii> iii;

ll pwr(ll base, ll p, ll mod = MOD){
ll ans = 1;while(p){if(p&1)ans=(ans*base)%mod;base=(base*base)%mod;p/=2;}return ans;
}

ll gcd(ll a, ll b){
    if(b == 0)  return a;
    return gcd(b, a%b);
}

int n;
double p[100005], tree[2][100005];

void build(int node, int s, int e){
    if(s > e)   return;
    if(s == e){
// cout<<"yolo "<<node<<" "<<s<<" "<<p[s]<<" "<<(1.0 - p[s])/p[s]<<endl;
        assert(p[s] > 0);
        tree[0][node] = (1.0 - p[s])/p[s];
        tree[1][node] = (1.0 - p[s])/p[s];
        return;
    }
    int mid = (s+e)/2;
    build(LEFT(node), s, mid);
    build(RIGHT(node), mid+1, e);
    tree[0][node] = tree[0][LEFT(node)] + tree[1][LEFT(node)]*tree[0][RIGHT(node)];
    tree[1][node] = tree[1][LEFT(node)] * tree[1][RIGHT(node)];
}

void update(int node, int s, int e, int pos, double val){
    if(s > e || pos < s || pos > e) return;
    if(s == e){
        assert(val > 0);
        tree[0][node] = (1.0 - val)/val;
        tree[1][node] = (1.0 - val)/val;
        return;
    }
    int mid = (s+e)/2;
    update(LEFT(node), s, mid, pos, val);
    update(RIGHT(node), mid+1, e, pos, val);
    tree[0][node] = tree[0][LEFT(node)] + tree[1][LEFT(node)]*tree[0][RIGHT(node)];
    tree[1][node] = tree[1][LEFT(node)] * tree[1][RIGHT(node)];
}

pair<double, double> query(int node, int s, int e, int lo, int hi){
    if(s > e || lo > e || s > hi)   return pair<double, double> (0.0, 1.0);
    if(s >= lo && e <= hi){
// cout<<node<<" "<<s<<" "<<e<<" returns "<<tree[0][node]<<" "<<tree[1][node]<<endl;
        return pair<double, double> (tree[0][node], tree[1][node]);
    }
    int mid = (s+e)/2;
    pair<double, double> a = query(LEFT(node), s, mid, lo, hi);
    pair<double, double> b = query(RIGHT(node), mid+1, e, lo, hi);
    a.ff = a.ff + a.ss * b.ff;
    a.ss = a.ss * b.ss;
// cout<<node<<" "<<s<<" "<<e<<" returns "<<a.ff<<" "<<a.ss<<endl;
    return a;
}

int main(){

    // ios_base::sync_with_stdio(0);

    int q;
    scanf("%d%d", &n, &q);
    for(int i=1;i<=n;i++){
        int a, b;
        scanf("%d%d", &a, &b);
        p[i] = (1.0*a)/b;
    }

    build(1, 1, n);
// q=1;
    while(q--){

        int op;
        scanf("%d", &op);
        if(op == 1){

            int pos, a, b;
            scanf("%d%d%d", &pos, &a, &b);
            update(1, 1, n, pos, (1.0*a)/b);
        }
        else{

            int lo, hi;
            scanf("%d%d", &lo, &hi);
            pair<double, double> z = query(1, 1, n, lo, hi);
// cout<<z.ff<<" "<<z.ss<<endl;
            double ans = 1.0 / (1.0 + z.ff);
            printf("%.5lf\n", ans);
        }
    }

    return 0;
}


//satyaki3794
#include <bits/stdc++.h>
#define ff first
#define ss second
#define pb push_back
#define MOD (1000000007LL)
#define LEFT(n) (2*(n))
#define RIGHT(n) (2*(n)+1)

using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> ii;
typedef pair<int, ii> iii;

ll pwr(ll base, ll p, ll mod = MOD){
ll ans = 1;while(p){if(p&1)ans=(ans*base)%mod;base=(base*base)%mod;p/=2;}return ans;
}

ll gcd(ll a, ll b){
    if(b == 0)  return a;
    return gcd(b, a%b);
}

int n;
double p[100005], tree[2][400005];

void build(int node, int s, int e){
    if(s > e)   return;
    if(s == e){
// cout<<"yolo "<<node<<" "<<s<<" "<<p[s]<<" "<<(1.0 - p[s])/p[s]<<endl;
        assert(p[s] > 0);
        tree[0][node] = (1.0 - p[s])/p[s];
        tree[1][node] = (1.0 - p[s])/p[s];
        return;
    }
    int mid = (s+e)/2;
    build(LEFT(node), s, mid);
    build(RIGHT(node), mid+1, e);
    tree[0][node] = tree[0][LEFT(node)] + tree[1][LEFT(node)]*tree[0][RIGHT(node)];
    tree[1][node] = tree[1][LEFT(node)] * tree[1][RIGHT(node)];
}

void update(int node, int s, int e, int pos, double val){
    if(s > e || pos < s || pos > e) return;
    if(s == e){
        assert(val > 0);
        tree[0][node] = (1.0 - val)/val;
        tree[1][node] = (1.0 - val)/val;
        return;
    }
    int mid = (s+e)/2;
    update(LEFT(node), s, mid, pos, val);
    update(RIGHT(node), mid+1, e, pos, val);
    tree[0][node] = tree[0][LEFT(node)] + tree[1][LEFT(node)]*tree[0][RIGHT(node)];
    tree[1][node] = tree[1][LEFT(node)] * tree[1][RIGHT(node)];
}

pair<double, double> query(int node, int s, int e, int lo, int hi){
    if(s > e || lo > e || s > hi)   return pair<double, double> (0.0, 1.0);
    if(s >= lo && e <= hi){
// cout<<node<<" "<<s<<" "<<e<<" returns "<<tree[0][node]<<" "<<tree[1][node]<<endl;
        return pair<double, double> (tree[0][node], tree[1][node]);
    }
    int mid = (s+e)/2;
    pair<double, double> a = query(LEFT(node), s, mid, lo, hi);
    pair<double, double> b = query(RIGHT(node), mid+1, e, lo, hi);
    a.ff = a.ff + a.ss * b.ff;
    a.ss = a.ss * b.ss;
// cout<<node<<" "<<s<<" "<<e<<" returns "<<a.ff<<" "<<a.ss<<endl;
    return a;
}

int main(){

    // ios_base::sync_with_stdio(0);

    int q;
    scanf("%d%d", &n, &q);
    for(int i=1;i<=n;i++){
        int a, b;
        scanf("%d%d", &a, &b);
        p[i] = (1.0*a)/b;
    }

    build(1, 1, n);
// q=1;
    while(q--){

        int op;
        scanf("%d", &op);
        if(op == 1){

            int pos, a, b;
            scanf("%d%d%d", &pos, &a, &b);
            update(1, 1, n, pos, (1.0*a)/b);
        }
        else{

            int lo, hi;
            scanf("%d%d", &lo, &hi);
            pair<double, double> z = query(1, 1, n, lo, hi);
// cout<<z.ff<<" "<<z.ss<<endl;
            double ans = 0;
            if(z.ff < 1e30) ans = 1.0 / (1.0 + z.ff);
            printf("%.5lf\n", ans);
        }
    }

    return 0;
}


//satyaki3794
#include <bits/stdc++.h>
#define ff first
#define ss second
#define pb push_back
#define MOD (1000000007LL)
#define LEFT(n) (2*(n))
#define RIGHT(n) (2*(n)+1)

using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> ii;
typedef pair<int, ii> iii;

ll pwr(ll base, ll p, ll mod = MOD){
ll ans = 1;while(p){if(p&1)ans=(ans*base)%mod;base=(base*base)%mod;p/=2;}return ans;
}

ll gcd(ll a, ll b){
    if(b == 0)  return a;
    return gcd(b, a%b);
}

int n;
double p[100005], tree[2][400005];

void build(int node, int s, int e){
    if(s > e)   return;
    if(s == e){
// cout<<"yolo "<<node<<" "<<s<<" "<<p[s]<<" "<<(1.0 - p[s])/p[s]<<endl;
        assert(p[s] > 0);
        tree[0][node] = (1.0 - p[s])/p[s];
        tree[1][node] = (1.0 - p[s])/p[s];
        return;
    }
    int mid = (s+e)/2;
    build(LEFT(node), s, mid);
    build(RIGHT(node), mid+1, e);
    tree[0][node] = tree[0][LEFT(node)] + tree[1][LEFT(node)]*tree[0][RIGHT(node)];
    tree[1][node] = tree[1][LEFT(node)] * tree[1][RIGHT(node)];
}

void update(int node, int s, int e, int pos, double val){
    if(s > e || pos < s || pos > e) return;
    if(s == e){
        assert(val > 0);
        tree[0][node] = (1.0 - val)/val;
        tree[1][node] = (1.0 - val)/val;
        return;
    }
    int mid = (s+e)/2;
    update(LEFT(node), s, mid, pos, val);
    update(RIGHT(node), mid+1, e, pos, val);
    tree[0][node] = tree[0][LEFT(node)] + tree[1][LEFT(node)]*tree[0][RIGHT(node)];
    tree[1][node] = tree[1][LEFT(node)] * tree[1][RIGHT(node)];
}

pair<double, double> query(int node, int s, int e, int lo, int hi){
    if(s > e || lo > e || s > hi)   return pair<double, double> (0.0, 1.0);
    if(s >= lo && e <= hi){
// cout<<node<<" "<<s<<" "<<e<<" returns "<<tree[0][node]<<" "<<tree[1][node]<<endl;
        return pair<double, double> (tree[0][node], tree[1][node]);
    }
    int mid = (s+e)/2;
    pair<double, double> a = query(LEFT(node), s, mid, lo, hi);
    pair<double, double> b = query(RIGHT(node), mid+1, e, lo, hi);
    a.ff = a.ff + a.ss * b.ff;
    a.ss = a.ss * b.ss;
// cout<<node<<" "<<s<<" "<<e<<" returns "<<a.ff<<" "<<a.ss<<endl;
    return a;
}

int main(){

    // ios_base::sync_with_stdio(0);

    int q;
    scanf("%d%d", &n, &q);
    for(int i=1;i<=n;i++){
        int a, b;
        scanf("%d%d", &a, &b);
        p[i] = (1.0*a)/b;
    }

    build(1, 1, n);
// q=1;
    while(q--){

        int op;
        scanf("%d", &op);
        if(op == 1){

            int pos, a, b;
            scanf("%d%d%d", &pos, &a, &b);
            update(1, 1, n, pos, (1.0*a)/b);
        }
        else{

            int lo, hi;
            scanf("%d%d", &lo, &hi);
            pair<double, double> z = query(1, 1, n, lo, hi);
// cout<<z.ff<<" "<<z.ss<<endl;
            double ans = 1.0 / (1.0 + z.ff);
            printf("%.5lf\n", ans);
        }
    }

    return 0;
}


//satyaki3794
#include <bits/stdc++.h>
#define ff first
#define ss second
#define pb push_back
#define MOD (1000000007LL)
#define LEFT(n) (2*(n))
#define RIGHT(n) (2*(n)+1)

using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> ii;
typedef pair<int, ii> iii;

ll pwr(ll base, ll p, ll mod = MOD){
ll ans = 1;while(p){if(p&1)ans=(ans*base)%mod;base=(base*base)%mod;p/=2;}return ans;
}

ll gcd(ll a, ll b){
    if(b == 0)  return a;
    return gcd(b, a%b);
}

int n;
double p[100005], tree[2][100005];

void build(int node, int s, int e){
    if(s > e)   return;
    if(s == e){
// cout<<"yolo "<<node<<" "<<s<<" "<<p[s]<<" "<<(1.0 - p[s])/p[s]<<endl;
        tree[0][node] = (1.0 - p[s])/p[s];
        tree[1][node] = (1.0 - p[s])/p[s];
        return;
    }
    int mid = (s+e)/2;
    build(LEFT(node), s, mid);
    build(RIGHT(node), mid+1, e);
    tree[0][node] = tree[0][LEFT(node)] + tree[1][LEFT(node)]*tree[0][RIGHT(node)];
    tree[1][node] = tree[1][LEFT(node)] * tree[1][RIGHT(node)];
}

void update(int node, int s, int e, int pos, double val){
    if(s > e || pos < s || pos > e) return;
    if(s == e){
        tree[0][node] = (1.0 - val)/val;
        tree[1][node] = (1.0 - val)/val;
        return;
    }
    int mid = (s+e)/2;
    update(LEFT(node), s, mid, pos, val);
    update(RIGHT(node), mid+1, e, pos, val);
    tree[0][node] = tree[0][LEFT(node)] + tree[1][LEFT(node)]*tree[0][RIGHT(node)];
    tree[1][node] = tree[1][LEFT(node)] * tree[1][RIGHT(node)];
}

pair<double, double> query(int node, int s, int e, int lo, int hi){
    if(s > e || lo > e || s > hi)   return pair<double, double> (0.0, 1.0);
    if(s >= lo && e <= hi){
// cout<<node<<" "<<s<<" "<<e<<" returns "<<tree[0][node]<<" "<<tree[1][node]<<endl;
        return pair<double, double> (tree[0][node], tree[1][node]);
    }
    int mid = (s+e)/2;
    pair<double, double> a = query(LEFT(node), s, mid, lo, hi);
    pair<double, double> b = query(RIGHT(node), mid+1, e, lo, hi);
    a.ff = a.ff + a.ss * b.ff;
    a.ss = a.ss * b.ss;
// cout<<node<<" "<<s<<" "<<e<<" returns "<<a.ff<<" "<<a.ss<<endl;
    return a;
}

int main(){

    // ios_base::sync_with_stdio(0);

    int q;
    scanf("%d%d", &n, &q);
    for(int i=1;i<=n;i++){
        int a, b;
        scanf("%d%d", &a, &b);
        p[i] = (1.0*a)/b;
    }

    build(1, 1, n);
// q=1;
    while(q--){

        int op;
        scanf("%d", &op);
        if(op == 1){

            int pos, a, b;
            scanf("%d%d%d", &pos, &a, &b);
            update(1, 1, n, pos, (1.0*a)/b);
        }
        else{

            int lo, hi;
            scanf("%d%d", &lo, &hi);
            pair<double, double> z = query(1, 1, n, lo, hi);
// cout<<z.ff<<" "<<z.ss<<endl;
            double ans = 1.0 / (1.0 + z.ff);
            printf("%.5lf\n", ans);
        }
    }

    return 0;
}


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

typedef long long ll;
typedef double db;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;

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

const ll MOD = 1e9+7;

inline void in() {}
template<class T, class... Ts>
inline void in(T& x, Ts&... xs) {
	int c, s=0; x=0;
	while (c=getchar(), c!='-'&&(c<'0'||c>'9'));
	if (c=='-') s=1, c=getchar();
	do x=x*10+(c-'0'); while (c=getchar(), c>='0'&&c<='9');
	if (s) x=-x;
	in(xs...);
}
inline void ins(char *s) {
    char c; while(c=getchar(), c<33); do *s++=c; while(c=getchar(), c>32); *s=0;
}

const int N=100000;

int n,q;
double p[N];

struct node {
	double p,r;
} m[N*2];

const int TIMES=200;
node comb(node a, node b) {
	node ans;
	ans.p=0;
	double k=a.p;
	rep(i,0,TIMES) {
		ans.p+=k*b.p;
		k*=(1-b.p)*a.r;
	}
	ans.r=b.r;
	k=(1-b.r)*a.r;
	rep(i,0,TIMES) {
		ans.r+=k*b.p;
		k*=(1-b.p)*a.r;
	}
	return ans;
}

void modify(int i) {
	m[i+N].p=m[i+N].r=p[i];
	for (i+=N,i/=2;i>=1;i/=2) m[i]=comb(m[2*i],m[2*i+1]);
}

double query(int l, int r) {
	node ansl, ansr;
	ansl.p=ansr.p=1;
	ansl.r=ansr.r=0;
	for (l+=N,r+=N+1;l<r;l/=2,r/=2) {
		if (l&1) ansl=comb(ansl, m[l++]);
		if (r&1) ansr=comb(m[--r], ansr);
	}
	return comb(ansl, ansr).p;
}

int main() {
	in(n,q);
	rep(i,0,n) {
		int a,b;
		in(a,b);
		p[i]=((double)a)/b;
		modify(i);
	}
	rep(kek,0,q) {
		int t;
		in(t);
		if (t==1) {
			int i,a,b;
			in(i,a,b);
			i--;
			p[i]=((double)a)/b;
			modify(i);
		} else {
			int i,j;
			in(i,j);
			i--;j--;
			printf("%.8f\n",query(i,j));
		}
	}
}


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

typedef long long ll;
typedef double db;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;

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

const ll MOD = 1e9+7;

inline void in() {}
template<class T, class... Ts>
inline void in(T& x, Ts&... xs) {
	int c, s=0; x=0;
	while (c=getchar(), c!='-'&&(c<'0'||c>'9'));
	if (c=='-') s=1, c=getchar();
	do x=x*10+(c-'0'); while (c=getchar(), c>='0'&&c<='9');
	if (s) x=-x;
	in(xs...);
}
inline void ins(char *s) {
    char c; while(c=getchar(), c<33); do *s++=c; while(c=getchar(), c>32); *s=0;
}

const int N=100000;

int n,q;
double p[N];

struct node {
	double p,r;
} m[N*2];

const int TIMES=400;
node comb(node a, node b) {
	node ans;
	ans.p=0;
	double k=a.p;
	rep(i,0,TIMES) {
		ans.p+=k*b.p;
		k*=(1-b.p)*a.r;
	}
	ans.r=b.r;
	k=(1-b.r)*a.r;
	rep(i,0,TIMES) {
		ans.r+=k*b.p;
		k*=(1-b.p)*a.r;
	}
	return ans;
}

void modify(int i) {
	m[i+N].p=m[i+N].r=p[i];
	for (i+=N,i/=2;i>=1;i/=2) m[i]=comb(m[2*i],m[2*i+1]);
}

double query(int l, int r) {
	node ansl, ansr;
	ansl.p=ansr.p=1;
	ansl.r=ansr.r=0;
	for (l+=N,r+=N+1;l<r;l/=2,r/=2) {
		if (l&1) ansl=comb(ansl, m[l++]);
		if (r&1) ansr=comb(m[--r], ansr);
	}
	return comb(ansl, ansr).p;
}

int main() {
	in(n,q);
	rep(i,0,n) {
		int a,b;
		in(a,b);
		p[i]=((double)a)/b;
		modify(i);
	}
	rep(kek,0,q) {
		int t;
		in(t);
		if (t==1) {
			int i,a,b;
			in(i,a,b);
			i--;
			p[i]=((double)a)/b;
			modify(i);
		} else {
			int i,j;
			in(i,j);
			i--;j--;
			printf("%.8f\n",query(i,j));
		}
	}
}


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

typedef long long ll;
typedef double db;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;

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

const ll MOD = 1e9+7;

inline void in() {}
template<class T, class... Ts>
inline void in(T& x, Ts&... xs) {
	int c, s=0; x=0;
	while (c=getchar(), c!='-'&&(c<'0'||c>'9'));
	if (c=='-') s=1, c=getchar();
	do x=x*10+(c-'0'); while (c=getchar(), c>='0'&&c<='9');
	if (s) x=-x;
	in(xs...);
}
inline void ins(char *s) {
    char c; while(c=getchar(), c<33); do *s++=c; while(c=getchar(), c>32); *s=0;
}

const int N=100000;

int n,q;
double p[N];

struct node {
	double p,r;
} m[N*2];

const int TIMES=20;
node comb(node a, node b) {
	node ans;
	ans.p=0;
	double k=a.p;
	rep(i,0,TIMES) {
		ans.p+=k*b.p;
		k*=(1-b.p)*a.r;
	}
	ans.r=b.r;
	k=(1-b.r)*a.r;
	rep(i,0,TIMES) {
		ans.r+=k*b.p;
		k*=(1-b.p)*a.r;
	}
	return ans;
}

void modify(int i) {
	m[i+N].p=m[i+N].r=p[i];
	for (i+=N,i/=2;i>=1;i/=2) m[i]=comb(m[2*i],m[2*i+1]);
}

double query(int l, int r) {
	node ansl, ansr;
	ansl.p=ansr.p=1;
	ansl.r=ansr.r=0;
	for (l+=N,r+=N+1;l<r;l/=2,r/=2) {
		if (l&1) ansl=comb(ansl, m[l++]);
		if (r&1) ansr=comb(m[--r], ansr);
	}
	return comb(ansl, ansr).p;
}

int main() {
	in(n,q);
	rep(i,0,n) {
		int a,b;
		in(a,b);
		p[i]=((double)a)/b;
		modify(i);
	}
	rep(kek,0,q) {
		int t;
		in(t);
		if (t==1) {
			int i,a,b;
			in(i,a,b);
			i--;
			p[i]=((double)a)/b;
			modify(i);
		} else {
			int i,j;
			in(i,j);
			i--;j--;
			printf("%.8f\n",query(i,j));
		}
	}
}


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

typedef long long ll;
typedef double db;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;

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

const ll MOD = 1e9+7;

inline void in() {}
template<class T, class... Ts>
inline void in(T& x, Ts&... xs) {
	int c, s=0; x=0;
	while (c=getchar(), c!='-'&&(c<'0'||c>'9'));
	if (c=='-') s=1, c=getchar();
	do x=x*10+(c-'0'); while (c=getchar(), c>='0'&&c<='9');
	if (s) x=-x;
	in(xs...);
}
inline void ins(char *s) {
    char c; while(c=getchar(), c<33); do *s++=c; while(c=getchar(), c>32); *s=0;
}

const int N=100000;

int n,q;
double p[N];

struct node {
	double p,r;
} m[N*2];

const int TIMES=333;
node comb(node a, node b) {
	node ans;
	ans.p=0;
	double k=a.p;
	rep(i,0,TIMES) {
		ans.p+=k*b.p;
		k*=(1-b.p)*a.r;
	}
	ans.r=b.r;
	k=(1-b.r)*a.r;
	rep(i,0,TIMES) {
		ans.r+=k*b.p;
		k*=(1-b.p)*a.r;
	}
	return ans;
}

void modify(int i) {
	m[i+N].p=m[i+N].r=p[i];
	for (i+=N,i/=2;i>=1;i/=2) m[i]=comb(m[2*i],m[2*i+1]);
}

double query(int l, int r) {
	node ansl, ansr;
	ansl.p=ansr.p=1;
	ansl.r=ansr.r=0;
	for (l+=N,r+=N+1;l<r;l/=2,r/=2) {
		if (l&1) ansl=comb(ansl, m[l++]);
		if (r&1) ansr=comb(m[--r], ansr);
	}
	return comb(ansl, ansr).p;
}

int main() {
	in(n,q);
	rep(i,0,n) {
		int a,b;
		in(a,b);
		p[i]=((double)a)/b;
		modify(i);
	}
	rep(kek,0,q) {
		int t;
		in(t);
		if (t==1) {
			int i,a,b;
			in(i,a,b);
			i--;
			p[i]=((double)a)/b;
			modify(i);
		} else {
			int i,j;
			in(i,j);
			i--;j--;
			printf("%.8f\n",query(i,j));
		}
	}
}


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

typedef long long ll;
typedef double db;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;

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

const ll MOD = 1e9+7;

inline void in() {}
template<class T, class... Ts>
inline void in(T& x, Ts&... xs) {
	int c, s=0; x=0;
	while (c=getchar(), c!='-'&&(c<'0'||c>'9'));
	if (c=='-') s=1, c=getchar();
	do x=x*10+(c-'0'); while (c=getchar(), c>='0'&&c<='9');
	if (s) x=-x;
	in(xs...);
}
inline void ins(char *s) {
    char c; while(c=getchar(), c<33); do *s++=c; while(c=getchar(), c>32); *s=0;
}

const int N=100000;

int n,q;
double p[N];

struct node {
	double p,r;
} m[N*2];

const int TIMES=100;
node comb(node a, node b) {
	node ans;
	ans.p=0;
	double k=a.p;
	rep(i,0,TIMES) {
		ans.p+=k*b.p;
		k*=(1-b.p)*a.r;
	}
	ans.r=b.r;
	k=(1-b.r)*a.r;
	rep(i,0,TIMES) {
		ans.r+=k*b.p;
		k*=(1-b.p)*a.r;
	}
	return ans;
}

void modify(int i) {
	m[i+N].p=m[i+N].r=p[i];
	for (i+=N,i/=2;i>=1;i/=2) m[i]=comb(m[2*i],m[2*i+1]);
}

double query(int l, int r) {
	node ansl, ansr;
	ansl.p=ansr.p=1;
	ansl.r=ansr.r=0;
	for (l+=N,r+=N+1;l<r;l/=2,r/=2) {
		if (l&1) ansl=comb(ansl, m[l++]);
		if (r&1) ansr=comb(m[--r], ansr);
	}
	return comb(ansl, ansr).p;
}

int main() {
	in(n,q);
	rep(i,0,n) {
		int a,b;
		in(a,b);
		p[i]=((double)a)/b;
		modify(i);
	}
	rep(kek,0,q) {
		int t;
		in(t);
		if (t==1) {
			int i,a,b;
			in(i,a,b);
			i--;
			p[i]=((double)a)/b;
			modify(i);
		} else {
			int i,j;
			in(i,j);
			i--;j--;
			printf("%.8f\n",query(i,j));
		}
	}
}


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

typedef long long ll;
typedef double db;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;

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

const ll MOD = 1e9+7;

inline void in() {}
template<class T, class... Ts>
inline void in(T& x, Ts&... xs) {
	int c, s=0; x=0;
	while (c=getchar(), c!='-'&&(c<'0'||c>'9'));
	if (c=='-') s=1, c=getchar();
	do x=x*10+(c-'0'); while (c=getchar(), c>='0'&&c<='9');
	if (s) x=-x;
	in(xs...);
}
inline void ins(char *s) {
    char c; while(c=getchar(), c<33); do *s++=c; while(c=getchar(), c>32); *s=0;
}

const int N=100000;

int n,q;
double p[N];

struct node {
	double p,r;
} m[N*2];

const int TIMES=30;
node comb(node a, node b) {
	node ans;
	ans.p=0;
	double k=a.p;
	rep(i,0,TIMES) {
		ans.p+=k*b.p;
		k*=(1-b.p)*a.r;
	}
	ans.r=b.r;
	k=(1-b.r)*a.r;
	rep(i,0,TIMES) {
		ans.r+=k*b.p;
		k*=(1-b.p)*a.r;
	}
	return ans;
}

void modify(int i) {
	m[i+N].p=m[i+N].r=p[i];
	for (i+=N,i/=2;i>=1;i/=2) m[i]=comb(m[2*i],m[2*i+1]);
}

double query(int l, int r) {
	node ansl, ansr;
	ansl.p=ansr.p=1;
	ansl.r=ansr.r=0;
	for (l+=N,r+=N+1;l<r;l/=2,r/=2) {
		if (l&1) ansl=comb(ansl, m[l++]);
		if (r&1) ansr=comb(m[--r], ansr);
	}
	return comb(ansl, ansr).p;
}

int main() {
	in(n,q);
	rep(i,0,n) {
		int a,b;
		in(a,b);
		p[i]=((double)a)/b;
		modify(i);
	}
	rep(kek,0,q) {
		int t;
		in(t);
		if (t==1) {
			int i,a,b;
			in(i,a,b);
			i--;
			p[i]=((double)a)/b;
			modify(i);
		} else {
			int i,j;
			in(i,j);
			i--;j--;
			printf("%.8f\n",query(i,j));
		}
	}
}


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

typedef long long ll;
typedef double db;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;

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

const ll MOD = 1e9+7;

inline void in() {}
template<class T, class... Ts>
inline void in(T& x, Ts&... xs) {
	int c, s=0; x=0;
	while (c=getchar(), c!='-'&&(c<'0'||c>'9'));
	if (c=='-') s=1, c=getchar();
	do x=x*10+(c-'0'); while (c=getchar(), c>='0'&&c<='9');
	if (s) x=-x;
	in(xs...);
}
inline void ins(char *s) {
    char c; while(c=getchar(), c<33); do *s++=c; while(c=getchar(), c>32); *s=0;
}

const int N=100000;

int n,q;
double p[N];

struct node {
	double p,r;
} m[N*2];

node comb(node a, node b) {
	node ans;
	ans.p=a.p*b.p/(1.0+a.r*(b.p-1));
	ans.r=b.r+a.r*b.p*(1-b.r)/(1-a.r*(1-b.p));
	return ans;
}

void modify(int i) {
	m[i+N].p=m[i+N].r=p[i];
	for (i+=N,i/=2;i>=1;i/=2) m[i]=comb(m[2*i],m[2*i+1]);
}

double query(int l, int r) {
	node ansl, ansr;
	ansl.p=ansr.p=1;
	ansl.r=ansr.r=0;
	for (l+=N,r+=N+1;l<r;l/=2,r/=2) {
		if (l&1) ansl=comb(ansl, m[l++]);
		if (r&1) ansr=comb(m[--r], ansr);
	}
	return comb(ansl, ansr).p;
}

int main() {
	in(n,q);
	rep(i,0,n) {
		int a,b;
		in(a,b);
		p[i]=((double)a)/b;
		modify(i);
	}
	rep(kek,0,q) {
		int t;
		in(t);
		if (t==1) {
			int i,a,b;
			in(i,a,b);
			i--;
			p[i]=((double)a)/b;
			modify(i);
		} else {
			int i,j;
			in(i,j);
			i--;j--;
			printf("%.8f\n",query(i,j));
		}
	}
}


#include <cstdio>
#include <iostream>
#define ld long double
#define ll long long

using namespace std;

inline ll read(){
    ll x = 0; int zf = 1; char ch = ' ';
    while (ch != '-' && (ch < '0' || ch > '9')) ch = getchar();
    if (ch == '-') zf = -1, ch = getchar();
    while (ch >= '0' && ch <= '9') x = x * 10 + ch - '0', ch = getchar(); return x * zf;
}

struct Node{
    ld l, r;
    Node(ld x = 0.0, ld y = 0.0){l = x, r = y;}
};

Node operator + (const Node &a, const Node& b){
    return (Node){a.l * b.l / (1 - a.r * (1 - b.l)), b.r + (a.r * b.l * (1 - b.r)) / (1 - a.r * (1 - b.l))};
}

Node p[200005];

int L[200005], R[200005];

ll a[100005], b[100005];

void build(int l, int r, int pos){
    L[pos] = l, R[pos] = r;
    if (l == r){
        p[pos] = (Node){(ld)a[l] / (ld)b[l], (ld)a[l] / (ld)b[l]};
        return;
    }
    int mid = (l + r) >> 1;
    build(l, mid, pos << 1);
    build(mid + 1, r, (pos << 1) + 1);
    p[pos] = p[pos << 1] + p[(pos << 1) + 1];
}

void modify(int u, int x, int y, int pos){
    if (L[pos] == u && u == R[pos]) {
        p[pos] = (Node){(ld)x / (ld)y, (ld)x / (ld)y};
        return;
    }
    int mid = (L[pos] + R[pos]) >> 1;
    if (u <= mid)
        modify(u, x, y, pos << 1);
    else
        modify(u, x, y, (pos << 1) + 1);
    p[pos] = p[pos << 1] + p[(pos << 1) + 1];
}

Node query(int l, int r, int pos){
    if (L[pos] == l && r == R[pos])
        return p[pos];
    int mid = (L[pos] + R[pos]) >> 1;
    if (r <= mid)
        return query(l, r, pos << 1);
    if (mid < l)
        return query(l, r, (pos << 1) + 1);
    return (query(l, mid, pos << 1) + query(mid + 1, r, (pos << 1) + 1));
}

int main(){
    int n = read(), m = read();
    for (int i = 1; i <= n; ++i)
        a[i] = read(), b[i] = read();
    build(1, n, 1);
    for (int I = 0; I < m; ++I){
        int op = read();
        if (op == 1){
            int i = read(), x = read(), y = read();
            modify(i, x, y, 1);
        }
        else{
            int l = read(), r = read();
            long double ans = query(l, r, 1).l;
            cout << ans << endl;
        }
    }
    return 0;
}


#include <cstdio>
#define ld long double
#define ll long long

inline ll read(){
    ll x = 0; int zf = 1; char ch = ' ';
    while (ch != '-' && (ch < '0' || ch > '9')) ch = getchar();
    if (ch == '-') zf = -1, ch = getchar();
    while (ch >= '0' && ch <= '9') x = x * 10 + ch - '0', ch = getchar(); return x * zf;
}

struct Node{
    ld l, r;
    Node(ld x = 0.0, ld y = 0.0){l = x, r = y;}
};

Node operator + (const Node &a, const Node& b){
    return (Node){a.l * b.l / (1 - a.r * (1 - b.l)), b.r + (a.r * b.l * (1 - b.r)) / (1 - a.r * (1 - b.l))};
}

Node p[200005];

int L[200005], R[200005];

ll a[100005], b[100005];

void build(int l, int r, int pos){
    L[pos] = l, R[pos] = r;
    if (l == r){
        p[pos] = (Node){(ld)a[l] / (ld)b[l], (ld)a[l] / (ld)b[l]};
        return;
    }
    int mid = (l + r) >> 1;
    build(l, mid, pos << 1);
    build(mid + 1, r, (pos << 1) + 1);
    p[pos] = p[pos << 1] + p[(pos << 1) + 1];
}

void modify(int u, int x, int y, int pos){
    if (L[pos] == u && u == R[pos]) {
        p[pos] = (Node){(ld)x / (ld)y, (ld)x / (ld)y};
        return;
    }
    int mid = (L[pos] + R[pos]) >> 1;
    if (u <= mid)
        modify(u, x, y, pos << 1);
    else
        modify(u, x, y, (pos << 1) + 1);
    p[pos] = p[pos << 1] + p[(pos << 1) + 1];
}

Node query(int l, int r, int pos){
    if (L[pos] == l && r == R[pos])
        return p[pos];
    int mid = (L[pos] + R[pos]) >> 1;
    if (r <= mid)
        return query(l, r, pos << 1);
    if (mid < l)
        return query(l, r, (pos << 1) + 1);
    return (query(l, mid, pos << 1) + query(mid + 1, r, (pos << 1) + 1));
}

int main(){
    int n = read(), m = read();
    for (int i = 1; i <= n; ++i)
        a[i] = read(), b[i] = read();
    build(1, n, 1);
    for (int I = 0; I < m; ++I){
        int op = read();
        if (op == 1){
            int i = read(), x = read(), y = read();
            modify(i, x, y, 1);
        }
        else{
            int l = read(), r = read();
            long double ans = query(l, r, 1).l;
            printf("%Lf\n", ans);
        }
    }
    return 0;
}


#include <cstdio>
#define ld long double
#define ll long long

inline ll read(){
    ll x = 0; int zf = 1; char ch = ' ';
    while (ch != '-' && (ch < '0' || ch > '9')) ch = getchar();
    if (ch == '-') zf = -1, ch = getchar();
    while (ch >= '0' && ch <= '9') x = x * 10 + ch - '0', ch = getchar(); return x * zf;
}

struct Node{
    ld l, r;
    Node(ld x = 0.0, ld y = 0.0){l = x, r = y;}
};

Node operator + (const Node &a, const Node& b){
    return (Node){a.l * b.l / (1 - a.r * (1 - b.l)), b.r + (a.r * b.l * (1 - b.r)) / (1 - a.r * (1 - b.l))};
}

Node p[200005];

int L[200005], R[200005];

ll a[100005], b[100005];

void build(int l, int r, int pos){
    L[pos] = l, R[pos] = r;
    if (l == r){
        p[pos] = (Node){(ld)a[l] / (ld)b[l], (ld)a[l] / (ld)b[l]};
        return;
    }
    int mid = (l + r) >> 1;
    build(l, mid, pos << 1);
    build(mid + 1, r, (pos << 1) + 1);
    p[pos] = p[pos << 1] + p[(pos << 1) + 1];
}

void modify(int u, int x, int y, int pos){
    if (L[pos] == u && u == R[pos]) {
        p[pos] = (Node){(ld)x / (ld)y, (ld)x / (ld)y};
        return;
    }
    int mid = (L[pos] + R[pos]) >> 1;
    if (u <= mid)
        modify(u, x, y, pos << 1);
    else
        modify(u, x, y, (pos << 1) + 1);
    p[pos] = p[pos << 1] + p[(pos << 1) + 1];
}

Node query(int l, int r, int pos){
    if (L[pos] == l && r == R[pos])
        return p[pos];
    int mid = (L[pos] + R[pos]) >> 1;
    if (r <= mid)
        return query(l, r, pos << 1);
    if (mid < l)
        return query(l, r, (pos << 1) + 1);
    return (query(l, mid, pos << 1) + query(mid + 1, r, (pos << 1) + 1));
}

int main(){
    int n = read(), m = read();
    for (int i = 1; i <= n; ++i)
        a[i] = read(), b[i] = read();
    build(1, n, 1);
    for (int I = 0; I < m; ++I){
        int op = read();
        if (op == 1){
            int i = read(), x = read(), y = read();
            modify(i, x, y, 1);
        }
        else{
            int l = read(), r = read();
            printf("%.10Lf\n", query(l, r, 1).l);
        }
    }
    return 0;
}


#include <cstdio>
#include <iostream>
#define ld long double
#define ll long long

using namespace std;

inline ll read(){
    ll x = 0; int zf = 1; char ch = ' ';
    while (ch != '-' && (ch < '0' || ch > '9')) ch = getchar();
    if (ch == '-') zf = -1, ch = getchar();
    while (ch >= '0' && ch <= '9') x = x * 10 + ch - '0', ch = getchar(); return x * zf;
}

struct Node{
    ld l, r;
    Node(ld x = 0.0, ld y = 0.0){l = x, r = y;}
};

Node operator + (const Node &a, const Node& b){
    return (Node){a.l * b.l / (1 - a.r * (1 - b.l)), b.r + (a.r * b.l * (1 - b.r)) / (1 - a.r * (1 - b.l))};
}

Node p[2000005];

int L[2000005], R[2000005];

ll a[1000005], b[1000005];

void build(int l, int r, int pos){
    L[pos] = l, R[pos] = r;
    if (l == r){
        p[pos] = (Node){(ld)a[l] / (ld)b[l], (ld)a[l] / (ld)b[l]};
        return;
    }
    int mid = (l + r) >> 1;
    build(l, mid, pos << 1);
    build(mid + 1, r, (pos << 1) + 1);
    p[pos] = p[pos << 1] + p[(pos << 1) + 1];
}

void modify(int u, int x, int y, int pos){
    if (L[pos] == u && u == R[pos]) {
        p[pos] = (Node){(ld)x / (ld)y, (ld)x / (ld)y};
        return;
    }
    int mid = (L[pos] + R[pos]) >> 1;
    if (u <= mid)
        modify(u, x, y, pos << 1);
    else
        modify(u, x, y, (pos << 1) + 1);
    p[pos] = p[pos << 1] + p[(pos << 1) + 1];
}

Node query(int l, int r, int pos){
    if (L[pos] == l && r == R[pos])
        return p[pos];
    int mid = (L[pos] + R[pos]) >> 1;
    if (r <= mid)
        return query(l, r, pos << 1);
    if (mid < l)
        return query(l, r, (pos << 1) + 1);
    return (query(l, mid, pos << 1) + query(mid + 1, r, (pos << 1) + 1));
}

int main(){
    int n = read(), m = read();
    for (int i = 1; i <= n; ++i)
        a[i] = read(), b[i] = read();
    build(1, n, 1);
    for (int I = 0; I < m; ++I){
        int op = read();
        if (op == 1){
            int i = read(), x = read(), y = read();
            modify(i, x, y, 1);
        }
        else{
            int l = read(), r = read();
            long double ans = query(l, r, 1).l;
            cout << ans << endl;
        }
    }
    return 0;
}


//rejudge
#include <cstdio>
#include <iostream>
#define ld long double
#define ll long long

using namespace std;

inline ll read(){
    ll x = 0; int zf = 1; char ch = ' ';
    while (ch != '-' && (ch < '0' || ch > '9')) ch = getchar();
    if (ch == '-') zf = -1, ch = getchar();
    while (ch >= '0' && ch <= '9') x = x * 10 + ch - '0', ch = getchar(); return x * zf;
}

struct Node{
    ld l, r;
    Node(ld x = 0.0, ld y = 0.0){l = x, r = y;}
};

Node operator + (const Node &a, const Node& b){
    return (Node){a.l * b.l / (1 - a.r * (1 - b.l)), b.r + (a.r * b.l * (1 - b.r)) / (1 - a.r * (1 - b.l))};
}

Node p[2000005];

int L[2000005], R[2000005];

ll a[1000005], b[1000005];

void build(int l, int r, int pos){
    L[pos] = l, R[pos] = r;
    if (l == r){
        p[pos] = (Node){(ld)a[l] / (ld)b[l], (ld)a[l] / (ld)b[l]};
        return;
    }
    int mid = (l + r) >> 1;
    build(l, mid, pos << 1);
    build(mid + 1, r, (pos << 1) + 1);
    p[pos] = p[pos << 1] + p[(pos << 1) + 1];
}

void modify(int u, int x, int y, int pos){
    if (L[pos] == u && u == R[pos]) {
        p[pos] = (Node){(ld)x / (ld)y, (ld)x / (ld)y};
        return;
    }
    int mid = (L[pos] + R[pos]) >> 1;
    if (u <= mid)
        modify(u, x, y, pos << 1);
    else
        modify(u, x, y, (pos << 1) + 1);
    p[pos] = p[pos << 1] + p[(pos << 1) + 1];
}

Node query(int l, int r, int pos){
    if (L[pos] == l && r == R[pos])
        return p[pos];
    int mid = (L[pos] + R[pos]) >> 1;
    if (r <= mid)
        return query(l, r, pos << 1);
    if (mid < l)
        return query(l, r, (pos << 1) + 1);
    return (query(l, mid, pos << 1) + query(mid + 1, r, (pos << 1) + 1));
}

int main(){
    int n = read(), m = read();
    for (int i = 1; i <= n; ++i)
        a[i] = read(), b[i] = read();
    build(1, n, 1);
    for (int I = 0; I < m; ++I){
        int op = read();
        if (op == 1){
            int i = read(), x = read(), y = read();
            modify(i, x, y, 1);
        }
        else{
            int l = read(), r = read();
            long double ans = query(l, r, 1).l;
            cout << ans << endl;
        }
    }
    return 0;
}


#include<bits/stdc++.h>
using namespace std;
double b[1000000];
int n,m;
struct arr
{
	double x,y;
}a[1000000];
void build(int l,int r,int k)
{
	if(l==r)
	{
		a[k]={b[l],1-b[l]};
		return;
	}
	int mid=(l+r)>>1;
	build(l,mid,k*2);
	build(mid+1,r,k*2+1);
	double z=a[k*2+1].x+a[k*2].y-a[k*2+1].x*a[k*2].y;
	a[k]={a[k*2].x*a[k*2+1].x/z,a[k*2].y*a[k*2+1].y/z};
}
void update(int l,int r,int k,int x)
{
	if(l==r)
	{
		a[k]={b[l],1-b[l]};
		return;
	}
	int mid=(l+r)>>1;
	if(x<=mid) update(l,mid,k*2,x); else update(mid+1,r,k*2+1,x);
	double z=a[k*2+1].x+a[k*2].y-a[k*2+1].x*a[k*2].y;
	a[k]={a[k*2].x*a[k*2+1].x/z,a[k*2].y*a[k*2+1].y/z};
}
arr find(int l,int r,int k,int x,int y)
{
	if(x<=l&&y>=r) return a[k];
	int mid=(l+r)>>1;
	if(y<=mid) return find(l,mid,k*2,x,y);
	if(x>mid) return find(mid+1,r,k*2+1,x,y);
	arr p=find(l,mid,k*2,x,y),q=find(mid+1,r,k*2+1,x,y);
	double z=q.x+p.y-q.x*p.y;
	return {p.x*q.x/z,p.y*q.y/z};
}
int main()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++)
	{
		int x,y;
		scanf("%d%d",&x,&y);
		b[i]=1.0*x/y;
	}
	build(1,n,1);
	for(int i=1;i<=m;i++)
	{
		int bo,x,y,z;
		scanf("%d%d%d",&bo,&x,&y);
		if(bo-1) printf("%.20lf",find(1,n,1,x,y).x);
		else
		{
			scanf("%d",&z);
			b[x]=1.0*y/z;
			update(1,n,1,x);
		}
	}
}


#include<bits/stdc++.h>
using namespace std;
double b[1000000];
int n,m;
struct arr
{
	double x,y;
}a[1000000];
void build(int l,int r,int k)
{
	if(l==r)
	{
		a[k]={b[l],1-b[l]};
		return;
	}
	int mid=(l+r)>>1;
	build(l,mid,k*2);
	build(mid+1,r,k*2+1);
	double z=a[k*2+1].x+a[k*2].y-a[k*2+1].x*a[k*2].y;
	a[k]={a[k*2].x*a[k*2+1].x/z,a[k*2].y*a[k*2+1].y/z};
}
void update(int l,int r,int k,int x)
{
	if(l==r)
	{
		a[k]={b[l],1-b[l]};
		return;
	}
	int mid=(l+r)>>1;
	if(x<=mid) update(l,mid,k*2,x); else update(mid+1,r,k*2+1,x);
	double z=a[k*2+1].x+a[k*2].y-a[k*2+1].x*a[k*2].y;
	a[k]={a[k*2].x*a[k*2+1].x/z,a[k*2].y*a[k*2+1].y/z};
}
arr find(int l,int r,int k,int x,int y)
{
	if(x<=l&&y>=r) return a[k];
	int mid=(l+r)>>1;
	if(y<=mid) return find(l,mid,k*2,x,y);
	if(x>mid) return find(mid+1,r,k*2+1,x,y);
	arr p=find(l,mid,k*2,x,y),q=find(mid+1,r,k*2+1,x,y);
	double z=q.x+p.y-q.x*p.y;
	return {p.x*q.x/z,p.y*q.y/z};
}
int main()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++)
	{
		int x,y;
		scanf("%d%d",&x,&y);
		b[i]=1.0*x/y;
	}
	build(1,n,1);
	for(int i=1;i<=m;i++)
	{
		int bo,x,y,z;
		scanf("%d%d%d",&bo,&x,&y);
		if(bo-1) printf("%.20lf\n",find(1,n,1,x,y).x);
		else
		{
			scanf("%d",&z);
			b[x]=1.0*y/z;
			update(1,n,1,x);
		}
	}
}


#include <iostream>
#include <cmath>
#include <vector>
#include <map>
#include <set>
#include <string>
#include <cstring>
#include <queue>
#include <ctime>
#include <cassert>
#include <cstdio>
#include <algorithm>
#include <unordered_set>
#include <unordered_map>
#include <bitset>

using namespace std;

#define fr first
#define sc second
#define mp make_pair
#define pb push_back
#define epr(...) fprintf(stderr, __VA_ARGS__)
#define db(x) cerr << #x << " = " << x << endl
#define db2(x, y) cerr << "(" << #x << ", " << #y << ") = (" << x << ", " << y << ")\n";
#define db3(x, y, z) cerr << "(" << #x << ", " << #y << ", " << #z << ") = (" << x << ", " << y << ", " << z << ")\n"
#define all(a) (a).begin(), (a).end()

#define equal equalll
#define less lesss
#define set sett
const int N = 1e5 + 10;
const long long INF = 1e9 + 19;

struct Seg {
    double l, r;
    bool flag;
    Seg() { }
    Seg(double l, double r): l(l), r(r), flag(0) { }
    Seg(bool flag):flag(flag) { }
};

Seg merge(Seg w1, Seg w2) {
    if (w1.flag) return w2;
    if (w2.flag) return w1;
    double b = w2.l / (1 - (1 - w2.l) * w1.r);
    return Seg(w1.l * b, w2.r + (1 - w2.r) * w1.r * b);
}

int n, q;
double p[N];
Seg tree[N];

void build(int v, int ll, int rr) {
    if (ll + 1 == rr) {
        tree[v] = Seg(p[ll], p[ll]);
        return;
    }
    build(v * 2 + 1, ll, (ll + rr) / 2);
    build(v * 2 + 2, (ll + rr) / 2, rr);
    tree[v] = merge(tree[v * 2 + 1], tree[v * 2 + 2]);
}

void set(int v, int ll, int rr, int pos, double val) {
    if (pos < ll || rr <= pos) return;
    if (ll + 1 == rr) {
        tree[v] = Seg(val, val);
        return;
    }
    set(v * 2 + 1, ll, (ll + rr) / 2, pos, val);
    set(v * 2 + 2, (ll + rr) / 2, rr, pos, val);
    tree[v] = merge(tree[v * 2 + 1], tree[v * 2 + 2]);
}

Seg get(int v, int ll, int rr, int l, int r) {
    if (l >= rr || ll >= r) return Seg(1);
    if (l <= ll && rr <= r)
        return tree[v];
    return merge(get(v * 2 + 1, ll, (ll + rr) / 2, l, r),
                 get(v * 2 + 2, (ll + rr) / 2, rr, l, r));
}

void read() {
    scanf("%d%d", &n, &q);
    for (int i = 0; i < n; i++) {
        int x, y;
        scanf("%d%d", &x, &y);
        p[i] = x * 1.0 / y;
    }
}

void solve() {
    build(0, 0, n);
    for (int i = 0; i < q; i++) {
        int type;
        scanf("%d", &type);
        if (type == 2) {
            int l, r;
            scanf("%d%d", &l, &r); l--;
            Seg res = get(0, 0, n, l, r);
            printf("%.17f\n", res.l);
        }
        else {
            int pos, a, b;
            scanf("%d%d%d", &pos, &a, &b);
            set(0, 0, n, pos - 1, a * 1.0 / b);
        }
    }

}

void stress() {

}

int main(){
#ifdef MY_DEBUG
    freopen("in", "r", stdin);
    //freopen("out", "w", stdout);
#endif
    if (1) {
        int k = 1;
        for (int tt = 0; tt < k; tt++) {
            read();
            solve();
        }
    }
    else {
        stress();
    }

    return 0;
}


#include <iostream>
#include <cmath>
#include <vector>
#include <map>
#include <set>
#include <string>
#include <cstring>
#include <queue>
#include <ctime>
#include <cassert>
#include <cstdio>
#include <algorithm>
#include <unordered_set>
#include <unordered_map>
#include <bitset>

using namespace std;

#define fr first
#define sc second
#define mp make_pair
#define pb push_back
#define epr(...) fprintf(stderr, __VA_ARGS__)
#define db(x) cerr << #x << " = " << x << endl
#define db2(x, y) cerr << "(" << #x << ", " << #y << ") = (" << x << ", " << y << ")\n";
#define db3(x, y, z) cerr << "(" << #x << ", " << #y << ", " << #z << ") = (" << x << ", " << y << ", " << z << ")\n"
#define all(a) (a).begin(), (a).end()

#define equal equalll
#define less lesss
#define set sett
const int N = 4e5 + 10;
const long long INF = 1e9 + 19;

struct Seg {
    double l, r;
    bool flag;
    Seg() { }
    Seg(double l, double r): l(l), r(r), flag(0) { }
    Seg(bool flag):flag(flag) { }
};

Seg merge(Seg w1, Seg w2) {
    if (w1.flag) return w2;
    if (w2.flag) return w1;
    double b = w2.l / (1 - (1 - w2.l) * w1.r);
    return Seg(w1.l * b, w2.r + (1 - w2.r) * w1.r * b);
}

int n, q;
double p[N];
Seg tree[N];

void build(int v, int ll, int rr) {
    if (ll + 1 == rr) {
        tree[v] = Seg(p[ll], p[ll]);
        return;
    }
    build(v * 2 + 1, ll, (ll + rr) / 2);
    build(v * 2 + 2, (ll + rr) / 2, rr);
    tree[v] = merge(tree[v * 2 + 1], tree[v * 2 + 2]);
}

void set(int v, int ll, int rr, int pos, double val) {
    if (pos < ll || rr <= pos) return;
    if (ll + 1 == rr) {
        tree[v] = Seg(val, val);
        return;
    }
    set(v * 2 + 1, ll, (ll + rr) / 2, pos, val);
    set(v * 2 + 2, (ll + rr) / 2, rr, pos, val);
    tree[v] = merge(tree[v * 2 + 1], tree[v * 2 + 2]);
}

Seg get(int v, int ll, int rr, int l, int r) {
    if (l >= rr || ll >= r) return Seg(1);
    if (l <= ll && rr <= r)
        return tree[v];
    return merge(get(v * 2 + 1, ll, (ll + rr) / 2, l, r),
                 get(v * 2 + 2, (ll + rr) / 2, rr, l, r));
}

void read() {
    scanf("%d%d", &n, &q);
    for (int i = 0; i < n; i++) {
        int x, y;
        scanf("%d%d", &x, &y);
        p[i] = x * 1.0 / y;
    }
}

void solve() {
    build(0, 0, n);
    for (int i = 0; i < q; i++) {
        int type;
        scanf("%d", &type);
        if (type == 2) {
            int l, r;
            scanf("%d%d", &l, &r); l--;
            Seg res = get(0, 0, n, l, r);
            printf("%.17f\n", res.l);
        }
        else {
            int pos, a, b;
            scanf("%d%d%d", &pos, &a, &b);
            set(0, 0, n, pos - 1, a * 1.0 / b);
        }
    }

}

void stress() {

}

int main(){
#ifdef MY_DEBUG
    freopen("in", "r", stdin);
    //freopen("out", "w", stdout);
#endif
    if (1) {
        int k = 1;
        for (int tt = 0; tt < k; tt++) {
            read();
            solve();
        }
    }
    else {
        stress();
    }

    return 0;
}


#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=100009;
#define ls (x<<1)
#define rs (x<<1|1)
struct Tree
{
	double A,B;
} tr[N<<2];
double p[N];
int n,q;

inline void update(int x)
{
	tr[x].A=tr[ls].A*tr[rs].A;
	tr[x].B=tr[ls].B+tr[ls].A*tr[rs].B;
}

inline void build(int x,int l,int r)
{
	if(l==r)
	{
		tr[x].A=tr[x].B=p[l];
		return;
	}
	int mid=(l+r)>>1;
	build(ls,l,mid);
	build(rs,mid+1,r);
	update(x);
}

void change(int x,int l,int r,int pos,double v)
{
	if(l==r)
	{
		tr[x].A=tr[x].B=p[l];
		return;
	}
	int mid=(l+r)>>1;
	if(pos<=mid) change(ls,l,mid,pos,v);
	else change(rs,mid+1,r,pos,v);
	update(x);
}

double Query(int x,int l,int r,int L,int R)
{
	if(L<=l&&r<=R) return tr[x].A;
	int mid=(l+r)>>1;
	double res=1.0;
	if(L<=mid) res*=Query(ls,l,mid,L,R);
	if(R>mid) res*=Query(rs,mid+1,r,L,R);
	return res;
}

double query(int x,int l,int r,int L,int R)
{
	if(L<=l&&r<=R) return tr[x].B;
	int mid=(l+r)>>1;
	double res=0.0;
	if(L<=mid) res+=query(ls,l,mid,L,R);
	if(R>mid) res+=Query(ls,l,mid,L,mid)*query(rs,mid+1,r,L,R);
	return res;
}

int main()
{
	scanf("%d%d",&n,&q);
	for(int i=1;i<=n;i++)
	{
		int a,b;
		scanf("%d%d",&a,&b);
		p[i]=1.0*(b-a)/a;
	}
	build(1,1,n);
	while(q--)
	{
		int op,x,a,b,l,r;
		scanf("%d",&op);
		if(op==1)
		{
			scanf("%d%d%d",&x,&a,&b);
			p[x]=1.0*(b-a)/a;
			change(1,1,n,x,p[x]);
		}
		else
			scanf("%d%d",&l,&r),
			printf("%.5lf\n",1.0/(query(1,1,n,l,r)+1.0));
	}
	return 0;
}


#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;

#define Int register int
#define MAXN 100005

int n,m;

struct node
{
	int l,r;
	double sum1,sum2;
}tree[MAXN << 2];

int a[MAXN],b[MAXN];

double p[MAXN];

void Push_up (int i)
{
	tree[i].sum1 = tree[i << 1].sum1 * tree[i << 1 | 1].sum1;
	tree[i].sum2 = tree[i << 1].sum2 + tree[i << 1].sum1 * tree[i << 1 | 1].sum2;
}

void build (int i,int l,int r)
{
	tree[i].l = l,tree[i].r = r;
	if (l == r)
	{
		tree[i].sum1 = tree[i].sum2 = p[l];
		return ;
	}
	int mid = (l + r) >> 1;
	build (i << 1,l,mid);
	build (i << 1 | 1,mid + 1,r);
	Push_up (i);
}

double query1 (int i,int ql,int qr)
{
	if (tree[i].l >= ql && tree[i].r <= qr) return tree[i].sum1;
	int mid = (tree[i].l + tree[i].r) >> 1;
	double Ans = 1.0;
	if (ql <= mid) Ans = Ans * 1.0 * query1 (i << 1,ql,qr);
	if (qr > mid) Ans = Ans * 1.0 * query1 (i << 1 | 1,ql,qr);
	return Ans;
}

double query (int i,int ql,int qr)
{
	if (tree[i].l >= ql && tree[i].r <= qr) return tree[i].sum2;
	int mid = (tree[i].l + tree[i].r) >> 1;
	double Ans = 0.0;
	if (ql <= mid) Ans += 1.0 * query (i << 1,ql,qr);
	if (qr > mid) Ans += 1.0 * query (i << 1 | 1,ql,qr) * query1 (i << 1,ql,mid);
	return Ans;
}

void update (int i,int Index,double p)
{
	if (tree[i].l > Index || Index > tree[i].r) return ;
	if (tree[i].l == tree[i].r)
	{
		tree[i].sum1 = tree[i].sum2 = p;
		return ;
	}
	update (i << 1,Index,p);
	update (i << 1 | 1,Index,p);
	Push_up (i);
}

void read (int &x)
{
	x = 0;char c = getchar();int f = 1;
	while (c < '0' || c > '9'){if (c == '-') f = -f;c = getchar();}
	while (c >= '0' && c <= '9'){x = (x << 3) + (x << 1) + c - '0';c = getchar();}
	x *= f;return ;
}

void write (int x)
{
	if (x < 0){x = -x;putchar ('-');}
	if (x > 9) write (x / 10);
	putchar (x % 10 + '0');
}

signed main()
{
	read (n),read (m);
	for (Int i = 1;i <= n;++ i)
		read (a[i]),read (b[i]),
		p[i] = (b[i] - a[i]) * 1.0 / a[i];
	build (1,1,n);
	for (Int i = 1;i <= m;++ i)
	{
		int ope;
		read (ope);
		if (ope == 1)
		{
			int Index,a,b;
			read (Index),read (a),read (b);
			update (1,Index,a * 1.0 / b);
		}
		else
		{
			int l,r;
			read (l),read (r);
			printf ("%.10lf\n",1.0 / (query (1,l,r) + 1.0));
		}
	 }
}
/*
dp[i]=p[i-1]*dp[i-1]+(1-p[i+1])*dp[i+1]
p[i]*(dp[i+1]-dp[i-1])=dp[i]-dp[i-1]
g[i]=dp[i]-dp[i-1]
p[i]*(g[i+1]+g[i])=g[i]
g[i]*(1-p[i])/p[i]=g[i+1]
t[i]=(1-p[i])/p[i]
g[1]*(1+t[1]+t[1]*t[2]+..+t[1]*...t[n])=1
tree[i].sum1=t[l]*...*t[r]
tree[i].sum2=1+t[l]+t[l]*t[l+1]+..+t[l]*..*t[r]
tree[i].sum2=tree[ls].sum2+tree[ls].sum1*tree[rs].sum2
*/


#include<bits/stdc++.h>

using namespace std;

typedef long long ll;

const int maxn = 100000 + 5;
const int mod = 998244353;

int n, m;
double x[maxn], y[maxn], b[maxn];
double p[maxn];

double tag_add[maxn * 4], tag_mul[maxn * 4];
void inline pushdown(int id) {
	if(tag_mul[id] == 1 && tag_add[id] == 0) return;
	tag_mul[id << 1] = tag_mul[id << 1] * tag_mul[id];
	tag_mul[id << 1 | 1] = tag_mul[id << 1 | 1] * tag_mul[id];
	tag_add[id << 1] = tag_add[id << 1] * tag_mul[id] + tag_add[id];
	tag_add[id << 1 | 1] = tag_add[id << 1 | 1] * tag_mul[id] + tag_add[id];
	tag_mul[id] = 1, tag_add[id] = 0;
}
void radd(int id, int l, int r, int s, int t, double v)
{
	if(s <= l && t >= r) {
		tag_add[id] = tag_add[id] + v;
		return;
	}
	int mid = (l + r) >> 1;
	pushdown(id);
	if(s <= mid) radd(id << 1, l, mid, s, t, v);
	if(t > mid) radd(id << 1 | 1, mid + 1, r, s, t, v);
}
void rmul(int id, int l, int r, int s, int t, double v)
{
	if(s <= l && t >= r) {
		tag_mul[id] = tag_mul[id] * v;
		tag_add[id] = tag_add[id] * v;
		return;
	}
	int mid = (l + r) >> 1;
	pushdown(id);
	if(s <= mid) rmul(id << 1, l, mid, s, t, v);
	if(t > mid) rmul(id << 1 | 1, mid + 1, r, s, t, v);
}
void build(int id, int l, int r)
{
	tag_mul[id] = 1, tag_add[id] = 0;
	if(l == r) return;
	int mid = (l + r) >> 1;
	build(id << 1, l, mid);
	build(id << 1 | 1, mid + 1, r);
}
double inline pquery(int i)
{
	int id = 1, l = 1, r = n + 1;
	while(l < r) {
		pushdown(id);
		int mid = (l + r) >> 1;
		if(i <= mid) r = mid, id = id << 1;
		else l = mid + 1, id = id << 1 | 1;
	}
	p[i] = p[i] * tag_mul[id] + tag_add[id];
	tag_mul[id] = 1, tag_add[id] = 0;
	return p[i];
}

void inline Init()
{
	scanf("%d %d", &n, &m);
	for(int i = 1; i <= n; ++i) {
		scanf("%lf %lf", x + i, y + i);
	}
	p[0] = 0, p[1] = 1;
	for(int i = 1; i <= n; ++i) {
		p[i + 1] = (p[i] - p[i - 1]) * y[i] / x[i] + p[i - 1];
	}
	build(1, 1, n + 1);
}

int opt, l, r, d;
double nx, ny;

void inline Solve()
{
	while(m--)
	{
		scanf("%d", &opt);
		if(opt == 1) {
			scanf("%d", &d); scanf("%lf %lf", x + d, y + d);
			pquery(d), pquery(d - 1), pquery(d + 1);
			double np = (p[d] - p[d - 1]) * y[d] / x[d] + p[d - 1];
			double mul = ((np - p[d]) == (p[d + 1] - p[d])) ? 1 : ((np - p[d]) / (p[d + 1] - p[d]));
			double add = p[d];

			radd(1, 1, n + 1, d + 1, n + 1, -add);
			rmul(1, 1, n + 1, d + 1, n + 1, mul);
			radd(1, 1, n + 1, d + 1, n + 1, add);

		} else {
			scanf("%d %d", &l, &r);
			pquery(l), pquery(l - 1), pquery(r + 1);
			printf("%.10lf\n", (p[l] - p[l - 1]) / (p[r + 1] - p[l - 1]));
		}
	}
}

int main()
{
	Init();
	Solve();
	return 0;
}


#include<bits/stdc++.h>

using namespace std;

typedef long long ll;

const int maxn = 100000 + 5;
const int mod = 998244353;

int n, m;
double x[maxn], y[maxn], b[maxn];
double p[maxn];

double tag_add[maxn * 4], tag_mul[maxn * 4];
void inline pushdown(int id) {
	if(tag_mul[id] == 1 && tag_add[id] == 0) return;
	tag_mul[id << 1] = tag_mul[id << 1] * tag_mul[id];
	tag_mul[id << 1 | 1] = tag_mul[id << 1 | 1] * tag_mul[id];
	tag_add[id << 1] = tag_add[id << 1] * tag_mul[id] + tag_add[id];
	tag_add[id << 1 | 1] = tag_add[id << 1 | 1] * tag_mul[id] + tag_add[id];
	tag_mul[id] = 1, tag_add[id] = 0;
}
void radd(int id, int l, int r, int s, int t, double v)
{
	if(s <= l && t >= r) {
		tag_add[id] = tag_add[id] + v;
		return;
	}
	int mid = (l + r) >> 1;
	pushdown(id);
	if(s <= mid) radd(id << 1, l, mid, s, t, v);
	if(t > mid) radd(id << 1 | 1, mid + 1, r, s, t, v);
}
void rmul(int id, int l, int r, int s, int t, double v)
{
	if(s <= l && t >= r) {
		tag_mul[id] = tag_mul[id] * v;
		tag_add[id] = tag_add[id] * v;
		return;
	}
	int mid = (l + r) >> 1;
	pushdown(id);
	if(s <= mid) rmul(id << 1, l, mid, s, t, v);
	if(t > mid) rmul(id << 1 | 1, mid + 1, r, s, t, v);
}
void build(int id, int l, int r)
{
	tag_mul[id] = 1, tag_add[id] = 0;
	if(l == r) return;
	int mid = (l + r) >> 1;
	build(id << 1, l, mid);
	build(id << 1 | 1, mid + 1, r);
}
double inline pquery(int i)
{
	int id = 1, l = 1, r = n + 1;
	while(l < r) {
		pushdown(id);
		int mid = (l + r) >> 1;
		if(i <= mid) r = mid, id = id << 1;
		else l = mid + 1, id = id << 1 | 1;
	}
	p[i] = p[i] * tag_mul[id] + tag_add[id];
	tag_mul[id] = 1, tag_add[id] = 0;
	return p[i];
}

void inline Init()
{
	scanf("%d %d", &n, &m);
	for(int i = 1; i <= n; ++i) {
		scanf("%lf %lf", x + i, y + i);
	}
	p[0] = 0, p[1] = 1;
	for(int i = 1; i <= n; ++i) {
		p[i + 1] = (p[i] - p[i - 1]) * y[i] / x[i] + p[i - 1];
	}
	build(1, 1, n + 1);
}

int opt, l, r, d;
double nx, ny;

void inline Solve()
{
	while(m--)
	{
		scanf("%d", &opt);
		if(opt == 1) {
			scanf("%d", &d); scanf("%lf %lf", x + d, y + d);
			pquery(d), pquery(d - 1), pquery(d + 1);
			double np = (p[d] - p[d - 1]) * y[d] / x[d] + p[d - 1];
			double mul = ((np - p[d]) == (p[d + 1] - p[d])) ? 1 : ((np - p[d]) / (p[d + 1] - p[d]));
			double add = p[d];

			radd(1, 1, n + 1, d + 1, n + 1, -add);
			rmul(1, 1, n + 1, d + 1, n + 1, mul);
			radd(1, 1, n + 1, d + 1, n + 1, add);

		} else {
			scanf("%d %d", &l, &r);
			pquery(l), pquery(l - 1), pquery(r + 1);
			printf("%.10lf\n", ((p[l] - p[l - 1]) == (p[r + 1] - p[l - 1])) ? 1 : ((p[l] - p[l - 1]) / (p[r + 1] - p[l - 1])));
		}
	}
}

int main()
{
	Init();
	Solve();
	return 0;
}


/* 44pts */

#include<cstdio>

#define cg (c=getchar())
inline int read(){
	int x;bool f=true;char c;
	while(cg<'0' || '9'<c)if(c=='-')f=false;
	for(x=(c^48);'0'<=cg && c<='9';x=(x<<1)+(x<<3)+(c^48));
	return f?x:-x;
}
#undef cg

const int MOD=998244353;
const int MAXN=1e5;

inline int inv(int x,int n=MOD-2){
	int ret=1;
	for(;n>0;n>>=1){
		if(n&1)ret=1ll*ret*x%MOD;
		x=1ll*x*x%MOD;
	}return ret;
}

int f[MAXN+5];
int win[MAXN+5],fail[MAXN+5];
int N,Q;

inline void Init(){
	N=read(),Q=read();
	int x,y;
	for(int i=1;i<=N;++i){
		x=read(),y=read();
		win[i]=1ll*x*inv(y)%MOD;
		fail[i]=1ll*(y-x)*inv(y)%MOD;
	}
}

inline void solve1(){
	int opt,d,l,r;
	int a,b;
	while(Q--){
		opt=read();
		if(opt==1){
			d=read(),l=read(),r=read();
			win[d]=1ll*l*inv(r)%MOD;
			fail[d]=1ll*(r-l)*inv(r)%MOD;
		}else{
			l=read(),r=read();
			if(l==r){printf("%d\n",win[l]);continue;}
			a=1,b=fail[l+1];
			for(int i=l+1;i<r;++i){
				a=1ll*a*win[i-1]%MOD,b=1ll*b*win[i-1]%MOD;
				b=(MOD+1-b)%MOD;
				a=1ll*a*inv(b)%MOD;
				b=1ll*fail[i+1]*inv(b)%MOD;
			}
			a=1ll*a*win[r-1]%MOD,b=1ll*b*win[r-1]%MOD;
			b=(MOD+1-b)%MOD;
			a=1ll*a*inv(b)%MOD;
			printf("%lld\n",1ll*a*win[r]%MOD);
		}
	}
}

signed main(){
	// freopen("hs.in","r",stdin);
	// freopen("hs.out","w",stdout);
	Init();
	solve1();
	return 0;
}
/*

O(nq):线性递推
O(Q logn):加上一些数据结构优化 ?

*/


#include <cstdio>
#include <utility>

#define Int register int

using namespace std;

typedef pair<double, double> pdd;

const int MAXN = 1e5;
int n, q;
double p[MAXN + 5] = {};

class Segment_Tree {
private:
	struct Node {
		int l, r;
		double f, g;
	} Tree[MAXN << 2];

public:
	inline void Push_up ( const int i ) {
		double f1 = Tree[i << 1].f, f2 = Tree[i << 1 | 1].f;
		double g1 = Tree[i << 1].g, g2 = Tree[i << 1 | 1].g;
		Tree[i].f = f1 * f2 / ( 1 - ( 1 - f2 ) * ( 1 - g1 ) );
		Tree[i].g = g1 * g2 / ( 1 - ( 1 - f2 ) * ( 1 - g1 ) );
	}
	inline void Build ( const int i, const int l, const int r, double* p ) {
		Tree[i] = { l, r, 0.0, 0.0 };
		if ( l == r ) { Tree[i].f = p[l], Tree[i].g = 1 - p[l]; return ; }
		int mid = l + r >> 1;
		Build ( i << 1, l, mid, p ), Build ( i << 1 | 1, mid + 1, r, p );
		Push_up ( i );
	}
	inline void Update ( const int i, const int Indx, const double p ) {
		if ( Tree[i].r < Indx || Indx < Tree[i].l ) return ;
		if ( Tree[i].l == Indx && Tree[i].r == Indx ) {
			Tree[i].f = p, Tree[i].g = 1 - p;
			return ;
		}
		Update ( i << 1, Indx, p ), Update ( i << 1 | 1, Indx, p );
		Push_up ( i );
	}
	inline pdd Query ( const int i, const int l, const int r ) {
		Node &now = Tree[i];
		if ( l <= Tree[i].l && Tree[i].r <= r ) return { Tree[i].f, Tree[i].g };
		int mid = Tree[i].l + Tree[i].r >> 1;
		if ( r <= mid ) return Query ( i << 1, l, r );
		else if ( mid < l ) return Query ( i << 1 | 1, l, r );
		pdd lret = Query ( i << 1, l, mid ), rret = Query ( i << 1 | 1, mid + 1, r );
		return { lret.first * rret.first / ( 1 - ( 1 - rret.first ) * ( 1 - lret.second ) ),
				lret.second * rret.second / ( 1 - ( 1 - rret.first ) * ( 1 - lret.second ) ) };
	}
} SegTree;

inline int rint () {
	int x = 0, f = 1; char s = getchar ();
	for ( ; s < '0' || '9' < s; s = getchar () ) f = s == '-' ? -f : f;
	for ( ; '0' <= s && s <= '9'; s = getchar () ) x = ( x << 3 ) + ( x << 1 ) + ( s ^ '0' );
	return x * f;
}

inline void Work () {
	n = rint (), q = rint ();
	for ( Int i = 1; i <= n; ++ i ) p[i] = 1.0 * rint () / rint ();
	SegTree.Build ( 1, 1, n, p );
	for ( Int opt, i, a, b; q --; ) {
		opt = rint ();
		if ( opt & 1 ) {
			scanf ( "%d %d %d", &i, &a, &b );
			SegTree.Update ( 1, i, 1.0 * a / b );
		} else {
			scanf ( "%d %d", &a, &b );
			printf ( "%.10lf\n", SegTree.Query ( 1, a, b ).first );
		}
	}
}

int main () {
	Work ();
	return 0;
}

/*
3 1
1 3
1 2
2 3
2 2 3
*/


#include <cstdio>
#include <utility>
#include <vector>
using namespace std;
#define fir first
#define sec second

const int MAXN = 200000;
int n , q , u , v , op , dex , a , b;
double p[ MAXN + 5 ];
vector< int > Graph[ MAXN + 5 ];

int Size[ MAXN + 5 ] , Depth[ MAXN + 5 ] , Fa[ MAXN + 5 ] , Heaviest_son[ MAXN + 5 ];
int cnt , Top[ MAXN + 5 ] , Dfn[ MAXN + 5 ] , Rank[ MAXN + 5 ];

struct Point{
	int l , r;
	double f , g;
};
struct Segment_Tree{
    #define ls x << 1
    #define rs x << 1 | 1

	Point Tree[ 4 * MAXN + 5 ];

	void Pushup( int x ) {
		Tree[ x ].f = ( Tree[ ls ].f * Tree[ rs ].f ) / ( 1 - ( 1 - Tree[ rs ].f ) * ( 1 - Tree[ ls ].g ) );
		Tree[ x ].g = ( Tree[ ls ].g * Tree[ rs ].g ) / ( 1 - ( 1 - Tree[ rs ].f ) * ( 1 - Tree[ ls ].g ) );
	}
	void Build( int x , int l , int r , bool f ) {
		Tree[ x ].l = l , Tree[ x ].r = r;
		if( l == r ) {
			if( f == 0 )
				Tree[ x ].f = p[ Rank[ l ] ] , Tree[ x ].g = 1 - p[ Rank[ l ] ];
			else
				Tree[ x ].f = 1 - p[ Rank[ l ] ] , Tree[ x ].g = p[ Rank[ l ] ];
			return;
		}
		int Mid = ( l + r ) / 2;
		Build( ls , l , Mid , f );
		Build( rs , Mid + 1 , r , f );
		Pushup( x );
	}
	void Insert( int x , int l , int r , double k ) {
		if( r < Tree[ x ].l || Tree[ x ].r < l )
			return;
		if( l <= Tree[ x ].l && Tree[ x ].r <= r ) {
			Tree[ x ].f = k , Tree[ x ].g = 1 - k;
			return;
		}
		Insert( ls , l , r , k );
		Insert( rs , l , r , k );
		Pushup( x );
	}
	pair< double , double > Find( int x , int l , int r ) {
		if( l <= Tree[ x ].l && Tree[ x ].r <= r )
			return { Tree[ x ].f , Tree[ x ].g };
		int Mid = ( Tree[ x ].l + Tree[ x ].r ) / 2;
		if( r <= Mid ) return Find( ls , l , r );
		if( l > Mid )  return Find( rs , l , r );

		pair< double , double > lson = Find( ls , l ,r ) , rson = Find( rs , l , r );
		double f = lson.fir * rson.fir / ( 1 - ( 1 - rson.fir ) * ( 1 - lson.sec ) );
		double g = lson.sec * rson.sec / ( 1 - ( 1 - rson.fir ) * ( 1 - lson.sec ) );
		return { f , g };
	}
    #undef ls
    #undef rs
}Tree1 , Tree2;

void dfs1( int u , int fa ) {
	Fa[ u ] = fa , Depth[ u ] = Depth[ fa ] + 1 , Size[ u ] = 1;

	for( int i = 0 ; i < Graph[ u ].size( ) ; i ++ ) {
		int v = Graph[ u ][ i ];
		if( v == fa ) continue;
		dfs1( v , u ); Size[ u ] += Size[ v ];
		if( Size[ v ] > Size[ Heaviest_son[ u ] ] )
			Heaviest_son[ u ] = v;
	}
}
void dfs2( int u , int top ) {
	Top[ u ] = top , Dfn[ u ] = ++ cnt , Rank[ cnt ] = u;
	if( Heaviest_son[ u ] ) dfs2( Heaviest_son[ u ] , top );
	for( int i = 0 ; i < Graph[ u ].size( ) ; i ++ ) {
		int v = Graph[ u ][ i ];
		if( v != Fa[ u ] && v != Heaviest_son[ u ] ) dfs2( v , v );
	}
}
double Query_route( int u , int v ) {
	pair< double , double > Ans[ 2 ] , tmp;
    bool f[ 2 ] = { } , now = 0;

	if( Top[ u ] == Top[ v ] ) {
		bool fl = 0;
		if( Depth[ u ] > Depth[ v ] ) swap( u , v ) , fl = 1;
		return fl == 0 ? Tree1.Find( 1 , Dfn[ u ] , Dfn[ v ] ).fir : Tree2.Find( 1 , Dfn[ u ] , Dfn[ v ] ).fir;
	}

	while( Top[ u ] != Top[ v ] ) {
		if( Depth[ Top[ u ] ] < Depth[ Top[ v ] ] ) swap( u , v ) , now = 1;

		if( now )
			tmp = Tree1.Find( 1 , Dfn[ Top[ u ] ] , Dfn[ u ] );
		else
			tmp = Tree2.Find( 1 , Dfn[ Top[ u ] ] , Dfn[ u ] );

        if( !f[ now ] )
            Ans[ now ] = tmp , f[ now ] = 1;
        else {
        	if( now == 1 ) {
        		Ans[ now ].fir = ( tmp.fir * Ans[ now ].fir ) / ( 1 - ( 1 - Ans[ now ].fir ) * ( 1 - tmp.sec ) );
		        Ans[ now ].sec = ( tmp.sec * Ans[ now ].sec ) / ( 1 - ( 1 - Ans[ now ].fir ) * ( 1 - tmp.sec ) );
			}
			else {
				Ans[ now ].fir = ( Ans[ now ].fir * tmp.fir ) / ( 1 - ( 1 - tmp.fir ) * ( 1 - Ans[ now ].sec ) );
		        Ans[ now ].sec = ( Ans[ now ].sec * tmp.sec ) / ( 1 - ( 1 - tmp.fir ) * ( 1 - Ans[ now ].sec ) );
			}
        }
        u = Fa[ Top[ u ] ];
	}
	if( Depth[ u ] < Depth[ v ] ) swap( u , v ) , now = 1;

	if( now )
		tmp = Tree1.Find( 1 , Dfn[ Top[ u ] ] , Dfn[ u ] );
	else
		tmp = Tree2.Find( 1 , Dfn[ Top[ u ] ] , Dfn[ u ] );

    if( !f[ now ] )
        Ans[ now ] = tmp , f[ now ] = 1;
    else {
	    if( now == 1 ) {
        	Ans[ now ].fir = ( tmp.fir * Ans[ now ].fir ) / ( 1 - ( 1 - Ans[ now ].fir ) * ( 1 - tmp.sec ) );
		    Ans[ now ].sec = ( tmp.sec * Ans[ now ].sec ) / ( 1 - ( 1 - Ans[ now ].fir ) * ( 1 - tmp.sec ) );
		}
		else {
			Ans[ now ].fir = ( Ans[ now ].fir * tmp.fir ) / ( 1 - ( 1 - tmp.fir ) * ( 1 - Ans[ now ].sec ) );
		    Ans[ now ].sec = ( Ans[ now ].sec * tmp.sec ) / ( 1 - ( 1 - tmp.fir ) * ( 1 - Ans[ now ].sec ) );
		}
    }
	if( !f[ 0 ] ) Ans[ 0 ] = Tree2.Find( 1 , Dfn[ u ] , Dfn[ u ] );
	if( !f[ 1 ] ) Ans[ 1 ] = Tree1.Find( 1 , Dfn[ v ] , Dfn[ v ] );
    return ( Ans[ 0 ].fir * Ans[ 1 ].fir ) / ( 1 - ( 1 - Ans[ 1 ].fir ) * ( 1 - Ans[ 0 ].sec ) );
}

int main( ) {
	scanf("%d %d",&n,&q);
    for( int i = 1 ; i <= n ; i ++ )
        scanf("%d %d",&a,&b) , p[ i ] = a * 1.0 / b;
    for( int i = 1 ; i <= n - 1 ; i ++ ) {
        v=u+1;
        Graph[ u ].push_back( v );
		Graph[ v ].push_back( u );
    }

    dfs1( 1 , 0 );
    dfs2( 1 , 1 );
    Tree1.Build( 1 , 1 , n , 0 );
	Tree2.Build( 1 , 1 , n , 1 );

	while( q -- ) {
		scanf("%d",&op);
		if( op == 1 ) {
			scanf("%d %d %d",&dex,&a,&b);
			Tree1.Insert( 1 , dex , dex , a * 1.0 / b );
			Tree2.Insert( 1 , dex , dex , 1 - a * 1.0 / b );
		}
		else {
			scanf("%d %d",&a,&b);
			printf("%.6lf\n", Query_route( a , b ) );
		}
	}
	return 0;
}


#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;

#define Int register int
#define MAXN 100005

int n,m;

struct node
{
	int l,r;
	double sum1,sum2;
}tree[MAXN << 2];

int a[MAXN],b[MAXN];

double p[MAXN];

void Push_up (int i)
{
	tree[i].sum1 = tree[i << 1].sum1 * tree[i << 1 | 1].sum1;
	tree[i].sum2 = tree[i << 1].sum2 + tree[i << 1].sum1 * tree[i << 1 | 1].sum2;
}

void build (int i,int l,int r)
{
	tree[i].l = l,tree[i].r = r;
	if (l == r)
	{
		tree[i].sum1 = tree[i].sum2 = p[l];
		return ;
	}
	int mid = (l + r) >> 1;
	build (i << 1,l,mid);
	build (i << 1 | 1,mid + 1,r);
	Push_up (i);
}

double query1 (int i,int ql,int qr)
{
	if (tree[i].l >= ql && tree[i].r <= qr) return tree[i].sum1;
	int mid = (tree[i].l + tree[i].r) >> 1;
	double Ans = 1.0;
	if (ql <= mid) Ans = Ans * 1.0 * query1 (i << 1,ql,qr);
	if (qr > mid) Ans = Ans * 1.0 * query1 (i << 1 | 1,ql,qr);
	return Ans;
}

double query (int i,int ql,int qr)
{
	if (tree[i].l >= ql && tree[i].r <= qr) return tree[i].sum2;
	int mid = (tree[i].l + tree[i].r) >> 1;
	double Ans = 0.0;
	if (ql <= mid) Ans += 1.0 * query (i << 1,ql,qr);
	if (qr > mid) Ans += 1.0 * query (i << 1 | 1,ql,qr) * query1 (i << 1,ql,mid);
	return Ans;
}

void update (int i,int Index,double p)
{
	if (tree[i].l > Index || Index > tree[i].r) return ;
	if (tree[i].l == tree[i].r)
	{
		tree[i].sum1 = tree[i].sum2 = p;
		return ;
	}
	update (i << 1,Index,p);
	update (i << 1 | 1,Index,p);
	Push_up (i);
}

void read (int &x)
{
	x = 0;char c = getchar();int f = 1;
	while (c < '0' || c > '9'){if (c == '-') f = -f;c = getchar();}
	while (c >= '0' && c <= '9'){x = (x << 3) + (x << 1) + c - '0';c = getchar();}
	x *= f;return ;
}

void write (int x)
{
	if (x < 0){x = -x;putchar ('-');}
	if (x > 9) write (x / 10);
	putchar (x % 10 + '0');
}

signed main()
{
	read (n),read (m);
	for (Int i = 1;i <= n;++ i)
		read (a[i]),read (b[i]),
		p[i] = (b[i] - a[i]) * 1.0 / a[i];
	build (1,1,n);
	for (Int i = 1;i <= m;++ i)
	{
		int ope;
		read (ope);
		if (ope == 1)
		{
			int Index,a,b;
			read (Index),read (a),read (b);
			update (1,Index,(b - a) * 1.0 / a);
		}
		else
		{
			int l,r;
			read (l),read (r);
			printf ("%.10lf\n",1.0 / (query (1,l,r) + 1.0));
		}
	 }
}
/*
dp[i]=p[i-1]*dp[i-1]+(1-p[i+1])*dp[i+1]
p[i]*(dp[i+1]-dp[i-1])=dp[i]-dp[i-1]
g[i]=dp[i]-dp[i-1]
p[i]*(g[i+1]+g[i])=g[i]
g[i]*(1-p[i])/p[i]=g[i+1]
t[i]=(1-p[i])/p[i]
g[1]*(1+t[1]+t[1]*t[2]+..+t[1]*...t[n])=1
tree[i].sum1=t[l]*...*t[r]
tree[i].sum2=1+t[l]+t[l]*t[l+1]+..+t[l]*..*t[r]
tree[i].sum2=tree[ls].sum2+tree[ls].sum1*tree[rs].sum2
*/


#include <cstdio>

#define isLeaf( a ) ( segTree[a].l == segTree[a].r )

const double eps = 1e-8;
const int MAXN = 1e5 + 5;

template<typename _T>
void read( _T &x )
{
	x = 0;char s = getchar();int f = 1;
	while( s > '9' || s < '0' ){if( s == '-' ) f = -1; s = getchar();}
	while( s >= '0' && s <= '9' ){x = ( x << 3 ) + ( x << 1 ) + ( s - '0' ), s = getchar();}
	x *= f;
}

template<typename _T>
void write( _T x )
{
	if( x < 0 ){ putchar( '-' ); x = ( ~ x ) + 1; }
	if( 9 < x ){ write( x / 10 ); }
	putchar( x % 10 + '0' );
}

template<typename _T>
_T ABS( const _T a )
{
	return a < 0 ? -a : a;
}

struct segmentTreeNode
{
	int l, r;
	double f, g;
}segTree[MAXN << 2];

typedef struct result
{
	double f, g;
	result() { f = 0, g = 0; }
	result( const double F, const double G ) { f = F, g = G; }
}R;

double p[MAXN];
int N, M;

void upt( const int now )
{
	segTree[now].f = segTree[now << 1].f * segTree[now << 1 | 1].f / ( segTree[now << 1 | 1].f + segTree[now << 1].g - segTree[now << 1].g * segTree[now << 1 | 1].f );
	segTree[now].g = segTree[now << 1].g * segTree[now << 1 | 1].g / ( segTree[now << 1 | 1].f + segTree[now << 1].g - segTree[now << 1].g * segTree[now << 1 | 1].f );
}

R upt( const R v, const R w )
{
	R u;
	u.f = v.f * w.f / ( w.f + v.g - v.g * w.f );
	u.g = v.g * w.g / ( w.f + v.g - v.g * w.f );
	return u;
}

void build( const int now, const int left, const int right )
{
	segTree[now].l = left, segTree[now].r = right;
	if( isLeaf( now ) ) { segTree[now].f = p[left], segTree[now].g = 1 - p[left]; return; }
	build( now << 1, left, ( left + right ) >> 1 ), build( now << 1 | 1, ( ( left + right ) >> 1 ) + 1, right );
	upt( now );
}

void update( const int now, const int indx, const double val )
{
	if( indx < segTree[now].l || segTree[now].r < indx ) return ;
	if( indx <= segTree[now].l && segTree[now].r <= indx ) { segTree[now].f = val, segTree[now].g = 1 - val; return ; }
	if( isLeaf( now ) ) return ;
	update( now << 1, indx, val ), update( now << 1 | 1, indx, val );
	upt( now );
}

R query( const int now, const int segL, const int segR )
{
	if( segL <= segTree[now].l && segTree[now].r <= segR ) { return R( segTree[now].f, segTree[now].g ); }
	int mid = ( segTree[now].l + segTree[now].r ) >> 1;
	if( segR <= mid ) return query( now << 1, segL, segR );
	else if( segL > mid ) return query( now << 1 | 1, segL, segR );
	else return upt( query( now << 1, segL, segR ), query( now << 1 | 1, segL, segR ) );
}

bool equal( const double x, const double y = 0 ) { return ABS( x - y ) <= eps; }
double fix( const double x ) { return equal( x ) ? x + eps : ( equal( x, 1 ) ? x - eps : x ); }

int main()
{
	int a, b;
	read( N ), read( M );
	for( int i = 1 ; i <= N ; i ++ )
		read( a ), read( b ), p[i] = fix( 1.0 * a / b );
	int opt, pos;
	R t;
	build( 1, 1, N );
	while( M -- )
	{
		read( opt );
		if( opt & 1 )
		{
			read( pos ), read( a ), read( b );
			update( 1, pos, fix( 1.0 * a / b ) );
		}
		else
		{
			read( a ), read( b );
			t = query( 1, a, b );
			printf( "%.10lf\n", t.f );
		}
	}
	return 0;
}


// eddy1021
#include <bits/stdc++.h>
using namespace std;
typedef double D;
typedef long double LD;
typedef long long ll;
typedef long long LL;
typedef pair<int,int> PII;
typedef pair<LL,LL> PLL;
typedef pair<LD,LD> Pt;
typedef tuple<int,int,int> tiii;
typedef tuple<LL,LL,LL> tlll;
#define mod9 1000000009ll
#define mod7 1000000007ll
#define INF  1023456789ll
#define INF16 10000000000000000ll
#define FI first
#define SE second
#define X FI
#define Y SE
#define PB push_back
#define MP make_pair
#define MT make_tuple
#define eps 1e-9
#define SZ(x) (int)(x).size()
#define ALL(x) (x).begin(), (x).end()
#ifndef ONLINE_JUDGE
#define debug(...) printf(__VA_ARGS__)
#else
#define debug(...)
#endif
inline ll getint(){
  ll _x=0,_tmp=1; char _tc=getchar();
  while( (_tc<'0'||_tc>'9')&&_tc!='-' ) _tc=getchar();
  if( _tc == '-' ) _tc=getchar() , _tmp = -1;
  while(_tc>='0'&&_tc<='9') _x*=10,_x+=(_tc-'0'),_tc=getchar();
  return _x*_tmp;
}
inline ll add( ll _x , ll _y , ll _mod = mod7 ){
  ll _ = _x + _y;
  if( _ >= _mod ) _ -= _mod;
  return _;
}
inline ll sub( ll _x , ll _y , ll _mod = mod7 ){
  ll _ = _x - _y;
  if( _ < 0 ) _ += _mod;
  return _;
}
inline ll mul( ll _x , ll _y , ll _mod = mod7 ){
  ll _ = _x * _y;
  if( _ >= _mod ) _ %= _mod;
  return _;
}
ll mypow( ll _a , ll _x , ll _mod ){
  if( _x == 0 ) return 1ll;
  ll _tmp = mypow( _a , _x / 2 , _mod );
  _tmp = mul( _tmp , _tmp , _mod );
  if( _x & 1 ) _tmp = mul( _tmp , _a , _mod );
  return _tmp;
}
ll mymul( ll _a , ll _x , ll _mod ){
  if( _x == 0 ) return 0ll;
  ll _tmp = mymul( _a , _x / 2 , _mod );
  _tmp = add( _tmp , _tmp , _mod );
  if( _x & 1 ) _tmp = add( _tmp , _a , _mod );
  return _tmp;
}
inline bool equal( D _x ,  D _y ){
  return _x > _y - eps && _x < _y + eps;
}
int __ = 1 , _cs;
/*********default*********/
#define N 101010
void build(){

}
int n , q;
double p[ N ];
void init(){
  scanf( "%d%d" , &n , &q );
  for( int i = 1 ; i <= n ; i ++ ){
    int ai , bi; scanf( "%d%d" , &ai , &bi );
    p[ i ] = (double)ai / bi;
  }
}
#define K 1021
void solve(){
  while( q -- ){
    int cmd; scanf( "%d" , &cmd );
    if( cmd == 1 ){
      int i , ai , bi;
      scanf( "%d%d%d" , &i , &ai , &bi );
      p[ i ] = (double)ai / bi;
    }else{
      int l , r;
      scanf( "%d%d" , &l , &r );
      double prob = 1.0 , pre = 0.0;
      for( int i = l , j = 0 ; i <= r && j < K ; i ++ , j ++ ){
        double now = p[ i ] / ( 1.0 - ( 1.0 - p[ i ] ) * pre );
        prob *= now;
        pre = now;
      }
      printf( "%.9f\n" , prob );
    }
  }
}
int main(){
  build();
  //__ = getint();
  while( __ -- ){
    init();
    solve();
  }
}