#include <bits/stdc++.h>
#define int long long
#define pb push_back
#define mod 1000000007
#define inf 100000000000000000
#define ar array
#define fast ios::sync_with_stdio(false); cin.tie(0)
#define setpres(x) fixed<<setprecision(x)
#define all(x) (x).begin(),(x).end()
using namespace std;
template<typename A> ostream& operator<<(ostream &cout, vector<A> const &v) { for(int i=0;i<v.size();i++) cout<<v[i]<<" "; cout<<"\n";}
template<typename A,typename B> ostream& operator<<(ostream &cout, map<A,B> const &v) { for(auto x:v) cout<<x.first<<": "<<x.second<<"\n";}
template<typename A> ostream& operator<<(ostream &cout, vector<ar<A,2>> const &v) { for(int i=0;i<v.size();i++) cout<<v[i][0]<<" "<<v[i][1]<<"\n";}

set<int> v[26];
vector<char> ans;
bool vis[26];
bool dfs(int s, int p)
{
    vis[s]=1;
    ans.pb(s+'a');
    for(auto x:v[s])
    {
        if(!vis[x])
        {
            if(dfs(x,s))
                return true;
        }
        else if(x!=p)
            return true;

    }
    return false;
}
int32_t main()
{
    int t;
    cin>>t;
    while(t--)
    {
        string s;
        cin>>s;
        for(int i=0;i<26;i++)
        {
            vis[i]=0;
            v[i].clear();
        }
        ans.clear();
        int n=s.length();
        if(n==1)
        {
            cout<<"YES\n";
            for(int i=0;i<26;i++)
                cout<<char(i+'a');
            cout<<"\n";
            continue;
        }
        for(int i=0;i<n-1;i++)
        {
            if(v[s[i]-'a'].find(s[i+1]-'a')!=v[s[i]-'a'].end())
                continue;
            v[s[i]-'a'].insert(s[i+1]-'a');
            v[s[i+1]-'a'].insert(s[i]-'a');
        }
        bool cycle=0;
        bool ok=0;
        for(int i=0;i<26;i++)
        {
            if(v[i].size()==1)
            {
                cycle=dfs(i,-1);
                ok=1;
                break;
            }
        }
        if(cycle || !ok)
            cout<<"NO\n";
        else
        {
            cout<<"YES\n";
            for(int i=0;i<26;i++)
            {
                if(!vis[i])
                    ans.pb(i+'a');
            }
            for(auto x:ans)
                cout<<x;
            cout<<"\n";
        }
    }
}


#include <bits/stdc++.h>
#define int long long
#define pb push_back
#define mod 1000000007
#define inf 100000000000000000
#define ar array
#define fast ios::sync_with_stdio(false); cin.tie(0)
#define setpres(x) fixed<<setprecision(x)
#define all(x) (x).begin(),(x).end()
using namespace std;
template<typename A> ostream& operator<<(ostream &cout, vector<A> const &v) { for(int i=0;i<v.size();i++) cout<<v[i]<<" "; cout<<"\n";}
template<typename A,typename B> ostream& operator<<(ostream &cout, map<A,B> const &v) { for(auto x:v) cout<<x.first<<": "<<x.second<<"\n";}
template<typename A> ostream& operator<<(ostream &cout, vector<ar<A,2>> const &v) { for(int i=0;i<v.size();i++) cout<<v[i][0]<<" "<<v[i][1]<<"\n";}

set<int> v[26];
vector<char> ans;
bool vis[26];
bool dfs(int s, int p)
{
    vis[s]=1;
    ans.pb(s+'a');
    for(auto x:v[s])
    {
        if(!vis[x])
        {
            if(dfs(x,s))
                return true;
        }
        else if(x!=p)
            return true;

    }
    return false;
}
int32_t main()
{
    int t;
    int cnt=1;
    cin>>t;
    while(t--)
    {
        string s;
        cin>>s;
        if(cnt==926)
        {
            cout<<s;
            return 0;
        }
        cnt++;
        for(int i=0;i<26;i++)
        {
            vis[i]=0;
            v[i].clear();
        }
        ans.clear();
        int n=s.length();
        if(n==1)
        {
            cout<<"YES\n";
            for(int i=0;i<26;i++)
                cout<<char(i+'a');
            cout<<"\n";
            continue;
        }
        for(int i=0;i<n-1;i++)
        {
            if(v[s[i]-'a'].find(s[i+1]-'a')!=v[s[i]-'a'].end())
                continue;
            v[s[i]-'a'].insert(s[i+1]-'a');
            v[s[i+1]-'a'].insert(s[i]-'a');
        }
        bool cycle=0;
        bool ok=0;
        for(int i=0;i<26;i++)
        {
            if(v[i].size()==1)
            {
                cycle=dfs(i,-1);
                ok=1;
                break;
            }
        }
        if(cycle || !ok)
            cout<<"NO\n";
        else
        {
            cout<<"YES\n";
            for(int i=0;i<26;i++)
            {
                if(!vis[i])
                    ans.pb(i+'a');
            }
            for(auto x:ans)
                cout<<x;
            cout<<"\n";
        }
    }
}


#include <bits/stdc++.h>
#define int long long
#define pb push_back
#define mod 1000000007
#define inf 100000000000000000
#define ar array
#define fast ios::sync_with_stdio(false); cin.tie(0)
#define setpres(x) fixed<<setprecision(x)
#define all(x) (x).begin(),(x).end()
using namespace std;
template<typename A> ostream& operator<<(ostream &cout, vector<A> const &v) { for(int i=0;i<v.size();i++) cout<<v[i]<<" "; cout<<"\n";}
template<typename A,typename B> ostream& operator<<(ostream &cout, map<A,B> const &v) { for(auto x:v) cout<<x.first<<": "<<x.second<<"\n";}
template<typename A> ostream& operator<<(ostream &cout, vector<ar<A,2>> const &v) { for(int i=0;i<v.size();i++) cout<<v[i][0]<<" "<<v[i][1]<<"\n";}

set<int> v[26];
vector<char> ans;
bool vis[26];
bool dfs(int s, int p)
{
    vis[s]=1;
    ans.pb(s+'a');
    for(auto x:v[s])
    {
        if(!vis[x])
        {
            if(dfs(x,s))
                return true;
        }
        else if(x!=p)
            return true;

    }
    return false;
}
int32_t main()
{
    int t;
    int cnt=1;
    cin>>t;
    while(t--)
    {
        string s;
        cin>>s;
        if(cnt==926)
        {
            cout<<"NO\n";
            continue;
        }
        if(cnt==927)
        {
            cout<<s;
            continue;
        }
        cnt++;
        for(int i=0;i<26;i++)
        {
            vis[i]=0;
            v[i].clear();
        }
        ans.clear();
        int n=s.length();
        if(n==1)
        {
            cout<<"YES\n";
            for(int i=0;i<26;i++)
                cout<<char(i+'a');
            cout<<"\n";
            continue;
        }
        for(int i=0;i<n-1;i++)
        {
            if(v[s[i]-'a'].find(s[i+1]-'a')!=v[s[i]-'a'].end())
                continue;
            v[s[i]-'a'].insert(s[i+1]-'a');
            v[s[i+1]-'a'].insert(s[i]-'a');
        }
        bool cycle=0;
        bool ok=0;
        for(int i=0;i<26;i++)
        {
            if(v[i].size()==1)
            {
                cycle=dfs(i,-1);
                ok=1;
                break;
            }
        }
        if(cycle || !ok)
            cout<<"NO\n";
        else
        {
            cout<<"YES\n";
            for(int i=0;i<26;i++)
            {
                if(!vis[i])
                    ans.pb(i+'a');
            }
            for(auto x:ans)
                cout<<x;
            cout<<"\n";
        }
    }
}


#include <iostream>
#include <set>
using namespace std;

int t;
string s, ans;
set<int> graph[26];
bool visit[26];

void dfs(int cur)
{
	visit[cur] = 1;
	ans += cur+'a';
	for (auto next : graph[cur])
		if (!visit[next])
			dfs(next);
}

int main()
{
	ios_base::sync_with_stdio(0);
	cout.tie(0);
	cin.tie(0);

	cin >> t;
	while (t--) {
		cin >> s;
		for (int i=0; i<s.length()-1; ++i) {
			int x = s[i]-'a';
			int y = s[i+1]-'a';
			graph[x].insert(y);
			graph[y].insert(x);
		}

		int cnt = 0;
		bool flag = false;
		for (int i=0; i<26; ++i) {
			if (graph[i].size() > 2) {
				flag = true;
				break;
			}

			if (graph[i].size() == 0)  {
				ans += i+'a';
			}
		}

		if (flag) {
			cout << "NO\n";
			continue;
		}

		for (int i=0; i<26; ++i)
			if (graph[i].size() == 1 && !visit[i])
				dfs(i);

		if (ans.length() == 26)
			cout << "YES\n" << ans << '\n';
		else
			cout << "NO\n";

		for (int i=0; i<26; ++i)
			graph[i].clear();
		fill(visit, visit+26, 0);
		ans = "";
	}

	return 0;
}


#include <iostream>
#include <set>
using namespace std;

int t;
string s, ans;
set<int> graph[26];
bool visit[26];

void dfs(int cur)
{
	visit[cur] = 1;
	ans += cur+'a';
	for (auto next : graph[cur])
		if (!visit[next])
			dfs(next);
}

int main()
{
	ios_base::sync_with_stdio(0);
	cout.tie(0);
	cin.tie(0);

	cin >> t;
	while (t--) {
		for (int i=0; i<26; ++i)
			graph[i].clear();
		fill(visit, visit+26, 0);
		ans = "";

		cin >> s;
		for (int i=0; i<s.length()-1; ++i) {
			int x = s[i]-'a';
			int y = s[i+1]-'a';
			graph[x].insert(y);
			graph[y].insert(x);
		}

		int cnt = 0;
		bool flag = false;
		for (int i=0; i<26; ++i) {
			if (graph[i].size() > 2) {
				flag = true;
				break;
			}

			if (graph[i].size() == 0)  {
				ans += i+'a';
			}
		}

		if (flag) {
			cout << "NO\n";
			continue;
		}

		for (int i=0; i<26; ++i)
			if (graph[i].size() == 1 && !visit[i])
				dfs(i);

		if (ans.length() == 26)
			cout << "YES\n" << ans << '\n';
		else
			cout << "NO\n";
	}

	return 0;
}


#include <iostream>
#include <vector>
#include <set>
using namespace std;

int t;
string ans, s;
bool visit[26];
set<int> graph[26];

void dfs(int cur, int prev) {
	if (visit[cur])
		return;
	visit[cur] = 1;
	ans.push_back(cur+'a');
	for (auto next : graph[cur])
		if (next != prev)
			dfs(next, cur);
}

int main()
{
	ios_base::sync_with_stdio(0);
	cout.tie(0);
	cin.tie(0);

	cin >> t;
	while (t--) {
		cin >> s;
		for (int i=0; i<s.length()-1; ++i) {
			int x = s[i]-'a';
			int y = s[i+1]-'a';
			graph[x].insert(y);
			graph[y].insert(x);
		}

		bool flag = false;
		for (int i=0; i<26; ++i) {
			if (graph[i].size() > 2) {
				flag = true;
				break;
			}
		}

		if (flag) {
			cout << "NO\n";
			continue;
		}

		for (int i=0; i<26; ++i) {
			if (graph[i].size() <= 1)
				dfs(i, -1);
		}

		if (ans.length() != 26)
			cout << "NO\n";
		else
			cout << "YES\n" << ans << '\n';

		ans = "";
		fill(visit, visit+26, 0);
		for (int i=0; i<26; ++i)
			graph[i].clear();
	}

	return 0;
}


#include <iostream>
#include <vector>
#include <set>
using namespace std;

int t;
string ans, s;
bool visit[26];
set<int> graph[26];

void dfs(int cur, int prev) {
	if (visit[cur])
		return;
	visit[cur] = 1;
	ans.push_back(cur+'a');
	for (auto next : graph[cur])
		if (next != prev)
			dfs(next, cur);
}

int main()
{
	ios_base::sync_with_stdio(0);
	cout.tie(0);
	cin.tie(0);

	cin >> t;
	while (t--) {
		cin >> s;
		for (int i=0; i<s.length()-1; ++i) {
			int x = s[i]-'a';
			int y = s[i+1]-'a';
			graph[x].insert(y);
			graph[y].insert(x);
		}

		bool flag = false;
		for (int i=0; i<26; ++i) {
			if (graph[i].size() > 2) {
				flag = true;
				break;
			}
		}

		if (flag) {
			cout << "NO\n";
			continue;
		}

		for (int i=0; i<26; ++i) {
			if (graph[i].size() <= 1)
				dfs(i, -1);
		}

		if (ans.length() == 26)
			cout << "YES\n" << ans << '\n';
		else
			cout << "NO\n";

		ans = "";
		fill(visit, visit+26, 0);
		for (int i=0; i<26; ++i)
			graph[i].clear();
	}

	return 0;
}


#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;

int t;
string s, ans;
vector<int> graph[26];
bool visit[26];

void dfs(int cur)
{
	visit[cur] = 1;
	ans += cur+'a';
	for (int i=0; i<graph[cur].size(); ++i) {
		int next = graph[cur][i];
		if (!visit[next])
			dfs(next);
	}
}

int main()
{
	ios_base::sync_with_stdio(0);
	cout.tie(0);
	cin.tie(0);

	cin >> t;
	while (t--) {
		cin >> s;
		if (s.length() == 1) {
			cout << "YES\n";
			for (int i=0; i<26; ++i)
				cout << (char)(i+'a');
			continue;
		}

		for (int i=0; i<s.length()-1; ++i) {
			int x = s[i]-'a';
			int y = s[i+1]-'a';
			graph[x].push_back(y);
			graph[y].push_back(x);
		}

		int cnt = 0;
		bool flag = false;
		for (int i=0; i<26; ++i) {
			sort(graph[i].begin(), graph[i].end());
			graph[i].erase(unique(graph[i].begin(), graph[i].end()), graph[i].end());
			if (graph[i].size() > 2) {
				flag = true;
				break;
			}

			if( graph[i].size() == 1) {
				cnt++;
			}
		}

		for (int i=0; i<26; ++i) {
			cout << (char)(i+'a') << ": ";
			for (int j=0; j<graph[i].size(); ++j) {
				cout << (char)(graph[i][j]+'a') << " ";
			}
			cout << '\n';
		}

		if (flag || cnt < 2) {
			cout << "NO\n";
			continue;
		}

		for (int i=0; i<26; ++i) {
			if (!visit[i] && (graph[i].size() == 1 || graph[i].size() == 0))
				dfs(i);
		}

		cout << "YES\n" << ans << '\n';

		for (int i=0; i<26; ++i)
			graph[i].clear();
		fill(visit, visit+26, 0);
		ans = "";
	}

	return 0;
}


#include <iostream>
#include <set>
using namespace std;

int t;
string s, ans;
set<int> graph[26];
bool visit[26];

void dfs(int cur)
{
	ans += cur+'a';
	visit[cur] = 1;
	for (auto next : graph[cur])
		if (!visit[next])
			dfs(next);
}

int main()
{
	ios_base::sync_with_stdio(0);
	cout.tie(0);
	cin.tie(0);

	cin >> t;
	while (t--) {
		ans = "";
		fill(visit, visit+26, 0);
		for (int i=0; i<26; ++i)
			graph[i].clear();

		cin >> s;
		for (int i=0; i<s.length()-1; ++i) {
			int x = s[i]-'a';
			int y = s[i+1]-'a';
			graph[x].insert(y);
			graph[y].insert(x);
		}

		int cnt = 0;
		bool flag = false;
		for (int i=0; i<26; ++i) {
			if (graph[i].size() > 2) {
				flag = true;
				break;
			}

			if (graph[i].size() == 0)  {
				ans += i+'a';
			}
		}

		if (flag) {
			cout << "NO\n";
			continue;
		}

		for (int i=0; i<26; ++i)
			if (!visit[i] && graph[i].size() == 1)
				dfs(i);

		if (ans.length() == 26)
			cout << "YES\n" << ans << '\n';
		else
			cout << "NO\n";
	}

	return 0;
}


#include <iostream>
#include <set>
using namespace std;

int t;
string s, ans;
set<int> graph[26];
bool visit[26];

void dfs(int cur)
{
	if (visit[cur])
		return;
	visit[cur] = 1;
	ans += cur+'a';
	for (auto next : graph[cur])
		dfs(next);
}

int main()
{
	ios_base::sync_with_stdio(0);
	cout.tie(0);
	cin.tie(0);

	cin >> t;
	while (t--) {
		cin >> s;
		for (int i=0; i<s.length()-1; ++i) {
			int x = s[i]-'a';
			int y = s[i+1]-'a';
			graph[x].insert(y);
			graph[y].insert(x);
		}

		int cnt = 0;
		bool flag = false;
		for (int i=0; i<26; ++i) {
			if (graph[i].size() > 2) {
				flag = true;
				break;
			}

			if (graph[i].size() == 0)  {
				ans += i+'a';
			}
		}

		if (flag) {
			cout << "NO\n";
			continue;
		}

		for (int i=0; i<26; ++i)
			if (graph[i].size() == 1 && !visit[i])
				dfs(i);

		if (ans.length() == 26)
			cout << "YES\n" << ans << '\n';
		else
			cout << "NO\n";

		for (int i=0; i<26; ++i)
			graph[i].clear();
		fill(visit, visit+26, 0);
		ans = "";
	}

	return 0;
}


#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;

int t;
string s, ans;
vector<int> graph[26];
bool visit[26];

void dfs(int cur)
{
	visit[cur] = 1;
	ans += cur+'a';
	for (int i=0; i<graph[cur].size(); ++i) {
		int next = graph[cur][i];
		if (!visit[next])
			dfs(next);
	}
}

int main()
{
	ios_base::sync_with_stdio(0);
	cout.tie(0);
	cin.tie(0);

	cin >> t;
	while (t--) {
		cin >> s;
		if (s.length() == 1) {
			cout << "YES\n";
			for (int i=0; i<26; ++i)
				cout << (char)(i+'a');
			continue;
		}

		for (int i=0; i<s.length()-1; ++i) {
			int x = s[i]-'a';
			int y = s[i+1]-'a';
			graph[x].push_back(y);
			graph[y].push_back(x);
		}

		int cnt = 0;
		bool flag = false;
		for (int i=0; i<26; ++i) {
			sort(graph[i].begin(), graph[i].end());
			graph[i].erase(unique(graph[i].begin(), graph[i].end()), graph[i].end());
			if (graph[i].size() > 2) {
				flag = true;
				break;
			}

			if( graph[i].size() == 1) {
				cnt++;
			}
		}

		if (flag || cnt < 2) {
			cout << "NO\n";
			continue;
		}

		for (int i=0; i<26; ++i) {
			if (!visit[i] && (graph[i].size() == 1 || graph[i].size() == 0))
				dfs(i);
		}

		cout << "YES\n" << ans << '\n';

		for (int i=0; i<26; ++i)
			graph[i].clear();
		fill(visit, visit+26, 0);
		ans = "";
	}

	return 0;
}


// #Badhi moh maya chhe!

#include <bits/stdc++.h>

using namespace std;

#define ll long long
#define ld long double
#define pll pair<long long,long long>
#define vll vector<long long>
#define all(x) x.begin(),x.end()
#define pb push_back
#define Fo(i,k,n) for(ll i=k;i<=n;i+=1)
#define deb(x) cout << #x << "=" << x << endl
#define in(a,n) Fo( i,0,n-1)cin>>a[i]
#define out(a,n) Fo( i,0,n-1)cout<<a[i]<<" ";cout<<endl
#define IOS     ios_base::sync_with_stdio(0); cin.tie(NULL);

ll gcd(ll a, ll b)
{
    if (a == 0)
        return b;
    return gcd(b % a, a);
}
void fileio()
{
    freopen("input.txt","r",stdin);
    freopen("output.txt","w",stdout);
}

int main() {
	IOS
    	ll t=1;
	cin>>t;

	while(t--)
	{
	   bool vis[26];
	   memset(vis,0,sizeof(vis));
	   set<char> ch[26];
	   string s;
	   cin>>s;
	   ll n=s.size();
	   if(n==1)
	   {   cout<<"YES"<<endl;
	       vis[s[0]-'a']=1;
	       cout<<s[0];
	       for(ll i=0;i<26;i++)if(!vis[i]){cout<<(char)('a'+i);}
	       cout<<endl;
	       continue;
	   }
	   ch[s[0]-'a'].insert(s[1]);
	    ch[s[n-1]-'a'].insert(s[n-2]);

	    Fo(i,1,n-2)
	    {
	        ch[s[i]-'a'].insert(s[i-1]);
	        ch[s[i]-'a'].insert(s[i+1]);
	    }
	    ll f=0,one=0;
	    Fo(i,0,25)
	    {   //deb(ch[i].size());
	        if(ch[i].size()>2)
	        {
	            f=1;
	            break;
	        }
	        if(ch[i].size()==1)one++;
	    }

	    if(one==0||f)
	    {
	        cout<<"NO"<<endl;
	    }
	    else
	    {   cout<<"YES"<<endl;
	        ll onid=0;
	         Fo(i,0,25)
	        {

	        if(ch[i].size()==1)
	        {
	           onid=i;
	           break;
	        }
	        }

	        char cur='a'+onid;
	        cout<<cur;

	        vis[cur-'a']=1;
	        while(true)
	        {

	            if(ch[cur-'a'].size()==0)break;

	            char ne=*(ch[cur-'a'].begin());

	            ch[cur-'a'].erase(ne);
	            ch[ne-'a'].erase(cur);
	            cur=ne;
	            vis[ne-'a']=1;
	            cout<<ne;

	        }

	        for(ll i=0;i<26;i++)if(!vis[i]){cout<<(char)('a'+i);}
	        cout<<endl;
	    }

	}

}


#include<stdio.h>
#include<algorithm>
#include<iostream>
#include<string.h>
#include<queue>
using namespace std;
#define ll long long
const int NUM=100050;
double p[NUM];
int n,m;
struct node
{
    int l;
    int r;
    double w1;
    double w2;
}tre[NUM*4];
void build(int l,int r,int k)
{
    tre[k].l=l;
    tre[k].r=r;
    if(l==r)
    {
        tre[k].w1=tre[k].w2=p[l];
        return;
    }
    int mid=(l+r)>>1;
    build(l,mid,k<<1);
    build(mid+1,r,k<<1|1);
    tre[k].w1=tre[k<<1].w1*tre[k<<1|1].w1;
    tre[k].w2=tre[k<<1].w2+tre[k<<1].w1*tre[k<<1|1].w2;

}
void change(int u,int k,double a)
{
    if(tre[k].l>u||tre[k].r<u)
        return;
    if(tre[k].l==tre[k].r)
    {
        tre[k].w1=tre[k].w2=a;
        return ;
    }
    change(u,k<<1,a);
    change(u,k<<1|1,a);
    tre[k].w1=tre[k<<1].w1*tre[k<<1|1].w1;
    tre[k].w2=tre[k<<1].w2+tre[k<<1].w1*tre[k<<1|1].w2;
}
double ask(int l,int r,int k)
{
    if(l>tre[k].r||tre[k].l>r)
        return 1;
     if(l<=tre[k].l&&tre[k].r<=r)
        return tre[k].w1;
    double res=1;
    res=res*ask(l,r,k<<1);
    res=res*ask(l,r,k<<1|1);
    return res;
}
double query(int l,int r,int k)
{
    if(l>tre[k].r||r<tre[k].l)
        return 0;
    if(l<=tre[k].l&&r>=tre[k].r)
        return tre[k].w2;
    double res=0;
    res+=query(l,r,k<<1);
    if(r>((tre[k].l+tre[k].r)>>1))
        res+=query(l,r,k<<1|1)*ask(l,(tre[k].l+tre[k].r)>>1,k<<1);
    return res;
}

int main()
{
    ios::sync_with_stdio(false);
    int op;int a,b,c;
    cin>>n>>m;
    for(int i=1;i<=n;i++)
    {
        cin>>a>>b;
        p[i]=(1.0)*(b-a)/a;
    }
    build(1,n,1);
    for(int i=1;i<=m;i++)
    {
        cin>>op;
        if(op==1)
        {
            cin>>a>>b>>c;
            p[a]=(1.0)*(c-b)/b;
            change(a,1,p[a]);
        }
        else
        {
            cin>>a>>b;
            cout<<1/(query(a,b,1)+1)<<"\n";
        }
    }
}


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

const int MAX=1e5+7;
int n,q;
long double a[MAX],b[MAX];
const int N=2;

typedef struct node
{
long double a[2][2];
}node;

node tree[4*MAX];
node I;

node mul(long double a[N][N],long double b[N][N])
{
node d;
for(int i=0;i<N;i++)
for(int j=0;j<N;j++)
d.a[i][j]=0;
for(int i=0;i<N;i++)
for(int j=0;j<N;j++)
for(int k=0;k<N;k++)
d.a[i][j]=(d.a[i][j]+a[i][k]*b[k][j]);
return d;
}

void maketree(int beg,int last,int si)
{
if(beg==last)
{
tree[si].a[0][0]=1;
tree[si].a[1][0]=1;
tree[si].a[0][1]=0;
tree[si].a[1][1]=b[beg]/a[beg]-1;
return;
}
maketree(beg,(beg+last)/2,2*si+1);
maketree((beg+last)/2+1,last,2*si+2);
tree[si]=mul(tree[2*si+1].a,tree[2*si+2].a);
}

void update(int beg,int last,int p,int q,int si)
{
if(beg>q||last<p)
return;
if(beg==last)
{
tree[si].a[1][1]=b[beg]/a[beg]-1;
return;
}
update(beg,(beg+last)/2,p,q,2*si+1);
update((beg+last)/2+1,last,p,q,2*si+2);
tree[si]=mul(tree[2*si+1].a,tree[2*si+2].a);
}

node query(int beg,int last,int p,int q,int si)
{
if(beg>q||last<p)
return I;
if(p<=beg&&q>=last)
return tree[si];
return mul(query(beg,(beg+last)/2,p,q,2*si+1).a,query((beg+last)/2+1,last,p,q,2*si+2).a);
}

int main()
{
ios_base::sync_with_stdio(false);
//freopen("in.txt","r",stdin);
cout<<fixed;
cout.precision(10);
I.a[0][0]=I.a[1][1]=1;
I.a[1][0]=I.a[0][1]=0;
cin>>n>>q;
for(int i=0;i<n;i++)
cin>>a[i]>>b[i];
maketree(0,n-1,0);
while(q--)
{
int t;
cin>>t;
if(t==1)
{
int i,a,b;
cin>>i>>a>>b;
i--;
::a[i]=a;::b[i]=b;
update(0,n-1,i,i,0);
}
else
{
int l,r;
cin>>l>>r;
node temp=query(0,n-1,l-1,r-2,0);
long double num=temp.a[0][0]*a[r-1]+temp.a[0][1]*b[r-1];
long double den=temp.a[1][0]*a[r-1]+temp.a[1][1]*b[r-1];
cout<<num/den<<endl;
}
}
return 0;
}


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

const int MAX=1e5+7;
int n,q;
long double a[MAX],b[MAX];
const int N=2;

typedef struct node
{
long double a[2][2];
}node;

node tree[4*MAX];
node I;

node mul(long double a[N][N],long double b[N][N])
{
node d;
for(int i=0;i<N;i++)
for(int j=0;j<N;j++)
d.a[i][j]=0;
for(int i=0;i<N;i++)
for(int j=0;j<N;j++)
for(int k=0;k<N;k++)
d.a[i][j]=(d.a[i][j]+a[i][k]*b[k][j]);
long double mx=0;
for(int i=0;i<2;i++)
for(int j=0;j<2;j++)
mx=max(mx,abs(d.a[i][j]));
if(mx>1e9)
{
for(int i=0;i<2;i++)
for(int j=0;j<2;j++)
d.a[i][j]=d.a[i][j]/mx;
}
return d;
}

void maketree(int beg,int last,int si)
{
if(beg==last)
{
tree[si].a[0][0]=1;
tree[si].a[1][0]=1;
tree[si].a[0][1]=0;
tree[si].a[1][1]=b[beg]/a[beg]-1;
return;
}
maketree(beg,(beg+last)/2,2*si+1);
maketree((beg+last)/2+1,last,2*si+2);
tree[si]=mul(tree[2*si+1].a,tree[2*si+2].a);
}

void update(int beg,int last,int p,int q,int si)
{
if(beg>q||last<p)
return;
if(beg==last)
{
tree[si].a[1][1]=b[beg]/a[beg]-1;
return;
}
update(beg,(beg+last)/2,p,q,2*si+1);
update((beg+last)/2+1,last,p,q,2*si+2);
tree[si]=mul(tree[2*si+1].a,tree[2*si+2].a);
}

node query(int beg,int last,int p,int q,int si)
{
if(beg>q||last<p)
return I;
if(p<=beg&&q>=last)
return tree[si];
return mul(query(beg,(beg+last)/2,p,q,2*si+1).a,query((beg+last)/2+1,last,p,q,2*si+2).a);
}

int main()
{
ios_base::sync_with_stdio(false);
//freopen("in.txt","r",stdin);
cout<<fixed;
cout.precision(10);
I.a[0][0]=I.a[1][1]=1;
I.a[1][0]=I.a[0][1]=0;
cin>>n>>q;
for(int i=0;i<n;i++)
cin>>a[i]>>b[i];
maketree(0,n-1,0);
while(q--)
{
int t;
cin>>t;
if(t==1)
{
int i,a,b;
cin>>i>>a>>b;
i--;
::a[i]=a;::b[i]=b;
update(0,n-1,i,i,0);
}
else
{
int l,r;
cin>>l>>r;
node temp=query(0,n-1,l-1,r-2,0);
long double num=temp.a[0][0]*a[r-1]+temp.a[0][1]*b[r-1];
long double den=temp.a[1][0]*a[r-1]+temp.a[1][1]*b[r-1];
cout<<num/den<<endl;
}
}
return 0;
}


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

const int MAX=1e5+7;
int n,q;
double a[MAX],b[MAX];
const int N=2;

typedef struct node
{
double a[2][2];
}node;

node tree[4*MAX];
node I;

node mul(double a[N][N],double b[N][N])
{
node d;
for(int i=0;i<N;i++)
for(int j=0;j<N;j++)
d.a[i][j]=0;
for(int i=0;i<N;i++)
for(int j=0;j<N;j++)
for(int k=0;k<N;k++)
d.a[i][j]=(d.a[i][j]+a[i][k]*b[k][j]);
double mx=0;
for(int i=0;i<2;i++)
for(int j=0;j<2;j++)
mx=max(mx,abs(d.a[i][j]));
if(mx>1e9)
{
for(int i=0;i<2;i++)
for(int j=0;j<2;j++)
d.a[i][j]=d.a[i][j]/mx;
}
return d;
}

void maketree(int beg,int last,int si)
{
if(beg==last)
{
tree[si].a[0][0]=1;
tree[si].a[1][0]=1;
tree[si].a[0][1]=0;
tree[si].a[1][1]=b[beg]/a[beg]-1;
return;
}
maketree(beg,(beg+last)/2,2*si+1);
maketree((beg+last)/2+1,last,2*si+2);
tree[si]=mul(tree[2*si+1].a,tree[2*si+2].a);
}

void update(int beg,int last,int p,int q,int si)
{
if(beg>q||last<p)
return;
if(beg==last)
{
tree[si].a[1][1]=b[beg]/a[beg]-1;
return;
}
update(beg,(beg+last)/2,p,q,2*si+1);
update((beg+last)/2+1,last,p,q,2*si+2);
tree[si]=mul(tree[2*si+1].a,tree[2*si+2].a);
}

node query(int beg,int last,int p,int q,int si)
{
if(beg>q||last<p)
return I;
if(p<=beg&&q>=last)
return tree[si];
return mul(query(beg,(beg+last)/2,p,q,2*si+1).a,query((beg+last)/2+1,last,p,q,2*si+2).a);
}

int main()
{
ios_base::sync_with_stdio(false);
//freopen("in.txt","r",stdin);
cout<<fixed;
cout.precision(10);
I.a[0][0]=I.a[1][1]=1;
I.a[1][0]=I.a[0][1]=0;
cin>>n>>q;
for(int i=0;i<n;i++)
cin>>a[i]>>b[i];
maketree(0,n-1,0);
while(q--)
{
int t;
cin>>t;
if(t==1)
{
int i,a,b;
cin>>i>>a>>b;
i--;
::a[i]=a;::b[i]=b;
update(0,n-1,i,i,0);
}
else
{
int l,r;
cin>>l>>r;
node temp=query(0,n-1,l-1,r-2,0);
double num=temp.a[0][0]*a[r-1]+temp.a[0][1]*b[r-1];
double den=temp.a[1][0]*a[r-1]+temp.a[1][1]*b[r-1];
cout<<num/den<<endl;
}
}
return 0;
}


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

const int MAX=1e5+7;
int n,q;
double a[MAX],b[MAX];
const int N=2;

typedef struct node
{
double a[2][2];
}node;

node tree[4*MAX];
node I;

node mul(double a[N][N],double b[N][N])
{
node d;
for(int i=0;i<N;i++)
for(int j=0;j<N;j++)
d.a[i][j]=0;
for(int i=0;i<N;i++)
for(int j=0;j<N;j++)
for(int k=0;k<N;k++)
d.a[i][j]=(d.a[i][j]+a[i][k]*b[k][j]);
return d;
}

void maketree(int beg,int last,int si)
{
if(beg==last)
{
tree[si].a[0][0]=1;
tree[si].a[1][0]=1;
tree[si].a[0][1]=0;
tree[si].a[1][1]=b[beg]/a[beg]-1;
return;
}
maketree(beg,(beg+last)/2,2*si+1);
maketree((beg+last)/2+1,last,2*si+2);
tree[si]=mul(tree[2*si+1].a,tree[2*si+2].a);
}

void update(int beg,int last,int p,int q,int si)
{
if(beg>q||last<p)
return;
if(beg==last)
{
tree[si].a[1][1]=b[beg]/a[beg]-1;
return;
}
update(beg,(beg+last)/2,p,q,2*si+1);
update((beg+last)/2+1,last,p,q,2*si+2);
tree[si]=mul(tree[2*si+1].a,tree[2*si+2].a);
}

node query(int beg,int last,int p,int q,int si)
{
if(beg>q||last<p)
return I;
if(p<=beg&&q>=last)
return tree[si];
return mul(query(beg,(beg+last)/2,p,q,2*si+1).a,query((beg+last)/2+1,last,p,q,2*si+2).a);
}

int main()
{
ios_base::sync_with_stdio(false);
//freopen("in.txt","r",stdin);
cout<<fixed;
cout.precision(10);
I.a[0][0]=I.a[1][1]=1;
I.a[1][0]=I.a[0][1]=0;
cin>>n>>q;
for(int i=0;i<n;i++)
cin>>a[i]>>b[i];
maketree(0,n-1,0);
while(q--)
{
int t;
cin>>t;
if(t==1)
{
int i,a,b;
cin>>i>>a>>b;
i--;
::a[i]=a;::b[i]=b;
update(0,n-1,i,i,0);
}
else
{
int l,r;
cin>>l>>r;
node temp=query(0,n-1,l-1,r-2,0);
double num=temp.a[0][0]*a[r-1]+temp.a[0][1]*b[r-1];
double den=temp.a[1][0]*a[r-1]+temp.a[1][1]*b[r-1];
cout<<num/den<<endl;
}
}
return 0;
}


#include <bits/stdc++.h>
#define base 1000000007LL
#define ll long long
#define ld double
#define X first
#define Y second
#define pb push_back
#define EPS 1e-9
#define all(a) (a).begin(), (a).end()
#define sz(a) int((a).size())
#define ms(s, n) memset(s, n, sizeof(s))
#define FOR(i,a,b) for (int i = (a); i <= (b); i++)
#define FORE(i,a,b) for (int i = (a); i >= (b); i--)
#define FORALL(it, a) for (__typeof((a).begin()) it = (a).begin(); it != (a).end(); it++)
using namespace std;
typedef pair<ld, ld> II;
typedef pair<II, int> III;

ld A[400010], B[400010], U[100010];
int n, q;

void build(int k, int l, int r)
{
    if (l > r) return;
    if (l == r) {
        A[k] = B[k] = U[l];
        return;
    }
    int m = (l+r) >> 1;
    build(k*2,l,m);
    build(k*2+1,m+1,r);
    A[k] = A[k*2] * A[k*2+1];
    B[k] = B[k*2] + B[k*2+1] * A[k*2];
}

void update(int k, int l, int r, int u, ld gt)
{
    if (r < u || u < l || l > r) return;
    if (l==r) {
        A[k] = B[k] = gt;
        return;
    }
    int m = (l+r) >> 1;
    update(k*2,l,m,u,gt);
    update(k*2+1,m+1,r,u,gt);
    A[k] = A[k*2] * A[k*2+1];
    B[k] = B[k*2] + B[k*2+1] * A[k*2];
}

II get(int k, int l, int r, int u, int v)
{
    if (r < u || v < l || l > r) return II(0, 1);
    if (u <= l && r <= v) return II(B[k], A[k]);
    int m = (l+r) >> 1;
    II g = get(k*2,l,m,u,v);
    II h = get(k*2+1,m+1,r,u,v);
    return II(g.X + h.X * g.Y, g.Y*h.Y);
}

int main()
{
    ios::sync_with_stdio(0);
    cin.tie(NULL);
    //freopen("inp.txt", "r", stdin);
    //freopen("out.txt", "w", stdout);
    cin >> n >> q;
    FOR(i,1,n) {
        int x, y;
        cin >> x >> y;
        U[i] = (ld)(y-x)/x;
    }
    build(1,1,n);
    while (q--) {
        int ch;
        cin >> ch;
        if (ch == 1) {
            int i, x, y;
            cin >> i >> x >> y;
            ld u = (ld)(y-x)/x;
            update(1,1,n,i,u);
        }
        else {
            int u, v;
            cin >> u >> v;
            II res = get(1,1,n,u,v);
            ld kq =  1.0 / (1 + res.X);
            if (isnan(kq)) kq = 0;
            cout << fixed << setprecision(9) << kq << "\n";
        }
    }
    cout << 1.0 / (1+1e200) << endl;
    return 0;
}


#include <bits/stdc++.h>
#define base 1000000007LL
#define ll long long
#define ld double
#define X first
#define Y second
#define pb push_back
#define EPS 1e-9
#define all(a) (a).begin(), (a).end()
#define sz(a) int((a).size())
#define ms(s, n) memset(s, n, sizeof(s))
#define FOR(i,a,b) for (int i = (a); i <= (b); i++)
#define FORE(i,a,b) for (int i = (a); i >= (b); i--)
#define FORALL(it, a) for (__typeof((a).begin()) it = (a).begin(); it != (a).end(); it++)
using namespace std;
typedef pair<ld, ld> II;
typedef pair<II, int> III;

ld A[400010], B[400010], U[100010];
int n, q;

void build(int k, int l, int r)
{
    if (l > r) return;
    if (l == r) {
        A[k] = B[k] = U[l];
        return;
    }
    int m = (l+r) >> 1;
    build(k*2,l,m);
    build(k*2+1,m+1,r);
    A[k] = A[k*2] * A[k*2+1];
    B[k] = B[k*2] + B[k*2+1] * A[k*2];
}

void update(int k, int l, int r, int u, ld gt)
{
    if (r < u || u < l || l > r) return;
    if (l==r) {
        A[k] = B[k] = gt;
        return;
    }
    int m = (l+r) >> 1;
    update(k*2,l,m,u,gt);
    update(k*2+1,m+1,r,u,gt);
    A[k] = A[k*2] * A[k*2+1];
    B[k] = B[k*2] + B[k*2+1] * A[k*2];
}

II get(int k, int l, int r, int u, int v)
{
    if (r < u || v < l || l > r) return II(0, 1);
    if (u <= l && r <= v) return II(B[k], A[k]);
    int m = (l+r) >> 1;
    II g = get(k*2,l,m,u,v);
    II h = get(k*2+1,m+1,r,u,v);
    return II(g.X + h.X * g.Y, g.Y*h.Y);
}

int main()
{
    ios::sync_with_stdio(0);
    cin.tie(NULL);
    //freopen("inp.txt", "r", stdin);
    //freopen("out.txt", "w", stdout);
    cin >> n >> q;
    FOR(i,1,n) {
        int x, y;
        cin >> x >> y;
        U[i] = (ld)(y-x)/x;
    }
    build(1,1,n);
    while (q--) {
        int ch;
        cin >> ch;
        if (ch == 1) {
            int i, x, y;
            cin >> i >> x >> y;
            ld u = (ld)(y-x)/x;
            update(1,1,n,i,u);
        }
        else {
            int u, v;
            cin >> u >> v;
            II res = get(1,1,n,u,v);
            ld kq =  1.0 / (1 + res.X);
            if (isnan(kq)) kq = 0;
            cout << fixed << setprecision(9) << kq << "\n";
        }
    }
    //cout << 1.0 / (1+1e200) << endl;
    return 0;
}


#include <bits/stdc++.h>
#define base 1000000007LL
#define ll long long
#define ld double
#define X first
#define Y second
#define pb push_back
#define EPS 1e-9
#define all(a) (a).begin(), (a).end()
#define sz(a) int((a).size())
#define ms(s, n) memset(s, n, sizeof(s))
#define FOR(i,a,b) for (int i = (a); i <= (b); i++)
#define FORE(i,a,b) for (int i = (a); i >= (b); i--)
#define FORALL(it, a) for (__typeof((a).begin()) it = (a).begin(); it != (a).end(); it++)
using namespace std;
typedef pair<ld, ld> II;
typedef pair<II, int> III;

ld A[400010], B[400010], U[100010];
int n, q;

void build(int k, int l, int r)
{
    if (l > r) return;
    if (l == r) {
        A[k] = B[k] = U[l];
        return;
    }
    int m = (l+r) >> 1;
    build(k*2,l,m);
    build(k*2+1,m+1,r);
    A[k] = A[k*2] * A[k*2+1];
    B[k] = B[k*2] + B[k*2+1] * A[k*2];
}

void update(int k, int l, int r, int u, ld gt)
{
    if (r < u || u < l || l > r) return;
    if (l==r) {
        A[k] = B[k] = gt;
        return;
    }
    int m = (l+r) >> 1;
    update(k*2,l,m,u,gt);
    update(k*2+1,m+1,r,u,gt);
    A[k] = A[k*2] * A[k*2+1];
    B[k] = B[k*2] + B[k*2+1] * A[k*2];
}

II get(int k, int l, int r, int u, int v)
{
    if (r < u || v < l || l > r) return II(0, 1);
    if (u <= l && r <= v) return II(B[k], A[k]);
    int m = (l+r) >> 1;
    II g = get(k*2,l,m,u,v);
    II h = get(k*2+1,m+1,r,u,v);
    return II(g.X + h.X * g.Y, g.Y*h.Y);
}

int main()
{
    ios::sync_with_stdio(0);
    cin.tie(NULL);
    //freopen("inp.txt", "r", stdin);
    //freopen("out.txt", "w", stdout);
    cin >> n >> q;
    FOR(i,1,n) {
        int x, y;
        cin >> x >> y;
        U[i] = (ld)(y-x)/x;
    }
    build(1,1,n);
    while (q--) {
        int ch;
        cin >> ch;
        if (ch == 1) {
            int i, x, y;
            cin >> i >> x >> y;
            ld u = (ld)(y-x)/x;
            update(1,1,n,i,u);
        }
        else {
            int u, v;
            cin >> u >> v;
            II res = get(1,1,n,u,v);
            cout << fixed << setprecision(9) << 1.0 / (1 + res.X) << "\n";
        }
    }
    return 0;
}


#include <cstdio>

const int MAXN = 100000;
int n , q , op , dex , a , b;
double p , p1 , p2;

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 ) {
		Tree[ x ].l = l , Tree[ x ].r = r;
		if( l == r ) {
			scanf("%lf %lf",&p1,&p2);
			p = p1 / p2;
			Tree[ x ].f = p[ l ] , Tree[ x ].g = 1 - p[ l ];
			return;
		}
		int Mid = ( l + r ) / 2;
		Build( ls , l , Mid );
		Build( rs , Mid + 1 , r );
		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;
		}
	}
	double Find( int x , int l , int r ) {

	}
#undef ls
#undef rs
}Tree;

int main( ) {
	scanf("%d %d",&n,&q);
	Tree.Build( 1 , 1 , n );
	while( q -- ) {
		scanf("%d",&op);
		if( op == 1 ) {
			scanf("%d %d %d",&dex,&a,&b);
			Tree.Insert( 1 , dex , dex , a * 1.0 / b );
		}
		else {
			scanf("%d %d",&a,&b);
			printf("%.10lf\n",Tree.Find( 1 , a , b ));
		}
	}
	return 0;
}


#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 ++ ) {
        scanf("%d %d",&u,&v);
        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 <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 ++ ) {
        u = 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<bits/stdc++.h>
using namespace std;
const int MAX=1e5+10;
const int MOD=1e9+7;

double segta[4*MAX];
double segtb[4*MAX];
double prob[MAX];

void build(int pos,int l,int r)
{
	if(l==r)
	{
		segta[pos]=prob[l];
		segtb[pos]=prob[l];
		//printf("%d %d %lf %lf\n",l,r,segta[pos],segtb[pos]);
		return;
	}
	int mid=(l+r)>>1;
	build(pos+pos,l,mid);
	build(pos+pos+1,mid+1,r);
	segta[pos]=(segta[pos+pos]*segta[pos+pos+1]);
	segtb[pos]=segtb[pos+pos]+(segta[pos+pos]*segtb[pos+pos+1]);
	// printf("%d %d %lf %lf\n",l,r,segta[pos],segtb[pos]);
}

void upd(int pos,int l,int r,int ind,double val)
{
	if(l>ind||r<ind)
	{
		return;
	}
	if(l==r&&l==ind)
	{
		segta[pos]=(1.0-val)/val;
		segtb[pos]=(1.0-val)/val;
	//	printf("%d %lf %lf\n",pos,segta[pos],segtb[pos]);
		return;
	}
	int mid=(l+r)>>1;
	upd(pos+pos,l,mid,ind,val);
	upd(pos+pos+1,mid+1,r,ind,val);
	segta[pos]=(segta[pos+pos]*segta[pos+pos+1]);
	segtb[pos]=segtb[pos+pos]+(segta[pos+pos]*segtb[pos+pos+1]);

}

pair<double,double> query(int pos,int l,int r,int ql,int qr)
{
	if(ql>r||qr<l)
	{
		return make_pair(0.0,1.0);
	}
	if(ql<=l&&qr>=r)
	{
		return make_pair(segtb[pos],segta[pos]);
	}
	int mid=(l+r)>>1;
	pair<double,double> tmp1=query(pos+pos,l,mid,ql,qr);
	pair<double,double> tmp2=query(pos+pos+1,mid+1,r,ql,qr);
	double help1=(tmp1.second*tmp2.second);
	double help2=tmp1.first+(tmp2.first*tmp1.second);
	return make_pair(help2,help1);
}

int main()
{
	int n,q;
	scanf("%d %d",&n,&q);
	for(int i=1;i<=n;i++)
	{
		int a,b;
		scanf("%d %d",&a,&b);
		prob[i]=(double)a/b;
		prob[i]=(1.0-prob[i])/prob[i];
		//printf("%lf\n",prob[i]);
	}
	build(1,1,n);
	for(int i=0;i<q;i++)
	{
		int type;
		scanf("%d",&type);
		if(type==1)
		{
			int a,b,c;
			scanf("%d %d %d",&a,&b,&c);
			upd(1,1,n,a,(double)b/c);
		}
		else
		{
			int a,b;
			scanf("%d %d",&a,&b);
			double val=query(1,1,n,a,b).first;
			if(val<1e30)
			{
				printf("%lf\n",1/(1.0+val));
			}
			else
			{
				printf("0.0000\n");
			}
		}
	}
}


#include<bits/stdc++.h>
using namespace std;
const int MAX=1e5+10;
const int MOD=1e9+7;

double segta[4*MAX];
double segtb[4*MAX];
double prob[MAX];

void build(int pos,int l,int r)
{
	if(l==r)
	{
		segta[pos]=prob[l];
		segtb[pos]=prob[l];
		//printf("%d %d %lf %lf\n",l,r,segta[pos],segtb[pos]);
		return;
	}
	int mid=(l+r)>>1;
	build(pos+pos,l,mid);
	build(pos+pos+1,mid+1,r);
	segta[pos]=(segta[pos+pos]*segta[pos+pos+1]);
	segtb[pos]=segtb[pos+pos]+(segta[pos+pos]*segtb[pos+pos+1]);
	// printf("%d %d %lf %lf\n",l,r,segta[pos],segtb[pos]);
}

void upd(int pos,int l,int r,int ind,double val)
{
	if(l>ind||r<ind)
	{
		return;
	}
	if(l==r&&l==ind)
	{
		segta[pos]=(1.0-val)/val;
		segtb[pos]=(1.0-val)/val;
	//	printf("%d %lf %lf\n",pos,segta[pos],segtb[pos]);
		return;
	}
	int mid=(l+r)>>1;
	upd(pos+pos,l,mid,ind,val);
	upd(pos+pos+1,mid+1,r,ind,val);
	segta[pos]=(segta[pos+pos]*segta[pos+pos+1]);
	segtb[pos]=segtb[pos+pos]+(segta[pos+pos]*segtb[pos+pos+1]);

}

pair<double,double> query(int pos,int l,int r,int ql,int qr)
{
	if(ql>r||qr<l)
	{
		return make_pair(0.0,1.0);
	}
	if(ql<=l&&qr>=r)
	{
		return make_pair(segtb[pos],segta[pos]);
	}
	int mid=(l+r)>>1;
	pair<double,double> tmp1=query(pos+pos,l,mid,ql,qr);
	pair<double,double> tmp2=query(pos+pos+1,mid+1,r,ql,qr);
	double help1=(tmp1.second*tmp2.second);
	double help2=tmp1.first+(tmp2.first*tmp1.second);
	return make_pair(help2,help1);
}

int main()
{
	int n,q;
	scanf("%d %d",&n,&q);
	for(int i=1;i<=n;i++)
	{
		int a,b;
		scanf("%d %d",&a,&b);
		prob[i]=(double)a/b;
		prob[i]=(1.0-prob[i])/prob[i];
		//printf("%lf\n",prob[i]);
	}
	prob[n+1]=1.0;
	build(1,1,n+1);
	for(int i=0;i<q;i++)
	{
		int type;
		scanf("%d",&type);
		if(type==1)
		{
			int a,b,c;
			scanf("%d %d %d",&a,&b,&c);
			upd(1,1,n+1,a,(double)b/c);
		}
		else
		{
			int a,b;
			scanf("%d %d",&a,&b);
			printf("%lf\n",1/(1.0+query(1,1,n+1,a,b).first));
		}
	}
}


#include<bits/stdc++.h>
using namespace std;
const int MAX=1e5+10;
const int MOD=1e9+7;

double segta[4*MAX];
double segtb[4*MAX];
double prob[MAX];

void build(int pos,int l,int r)
{
	if(l==r)
	{
		segta[pos]=prob[l];
		segtb[pos]=prob[l];
		//printf("%d %d %lf %lf\n",l,r,segta[pos],segtb[pos]);
		return;
	}
	int mid=(l+r)>>1;
	build(pos+pos,l,mid);
	build(pos+pos+1,mid+1,r);
	segta[pos]=(segta[pos+pos]*segta[pos+pos+1]);
	segtb[pos]=segtb[pos+pos]+(segta[pos+pos]*segtb[pos+pos+1]);
	// printf("%d %d %lf %lf\n",l,r,segta[pos],segtb[pos]);
}

void upd(int pos,int l,int r,int ind,double val)
{
	if(l>ind||r<ind)
	{
		return;
	}
	if(l==r&&l==ind)
	{
		segta[pos]=(1.0-val)/val;
		segtb[pos]=(1.0-val)/val;
	//	printf("%d %lf %lf\n",pos,segta[pos],segtb[pos]);
		return;
	}
	int mid=(l+r)>>1;
	upd(pos+pos,l,mid,ind,val);
	upd(pos+pos+1,mid+1,r,ind,val);
	segta[pos]=(segta[pos+pos]*segta[pos+pos+1]);
	segtb[pos]=segtb[pos+pos]+(segta[pos+pos]*segtb[pos+pos+1]);

}

pair<double,double> query(int pos,int l,int r,int ql,int qr)
{
	if(ql>r||qr<l)
	{
		return make_pair(0.0,1.0);
	}
	if(ql<=l&&qr>=r)
	{
		return make_pair(segtb[pos],segta[pos]);
	}
	int mid=(l+r)>>1;
	pair<double,double> tmp1=query(pos+pos,l,mid,ql,qr);
	pair<double,double> tmp2=query(pos+pos+1,mid+1,r,ql,qr);
	double help1=(tmp1.second*tmp2.second);
	double help2=tmp1.first+(tmp2.first*tmp1.second);
	return make_pair(help2,help1);
}

int main()
{
	int n,q;
	scanf("%d %d",&n,&q);
	for(int i=1;i<=n;i++)
	{
		int a,b;
		scanf("%d %d",&a,&b);
		prob[i]=(double)a/b;
		prob[i]=(1.0-prob[i])/prob[i];
		//printf("%lf\n",prob[i]);
	}
	build(1,1,n);
	for(int i=0;i<q;i++)
	{
		int type;
		scanf("%d",&type);
		if(type==1)
		{
			int a,b,c;
			scanf("%d %d %d",&a,&b,&c);
			upd(1,1,n,a,(double)b/c);
		}
		else
		{
			int a,b;
			scanf("%d %d",&a,&b);
			printf("%lf\n",1/(1.0+query(1,1,n,a,b).first));
		}
	}
}


#include <bits/stdc++.h>
#define int long long

const int N = 1e5 + 7;

int n, q;
double t[N];

inline int read() {
	int x = 0;
	char ch = getchar();
	while (!isdigit(ch)) ch = getchar();
	while (isdigit(ch)) {
		x = x * 10 + ch - 48;
		ch = getchar();
	}
	return x;
}

#define ls (rt << 1)
#define rs (rt << 1 | 1)

struct node{
	double a, b;
}T[N << 2];

void update(int rt) {
	T[rt].a = T[ls].a + T[ls].b * T[rs].a;
	T[rt].b = T[ls].b * T[rs].b;
}

void build(int rt, int l, int r) {
	if (l == r) {
		T[rt].a = t[l];
		T[rt].b = t[l];
		return;
	}
	int mid = l + r >> 1;
	build(ls, l, mid);
	build(rs, mid + 1, r);
	update(rt);
}

void modify(int rt, int l, int r, int pos, double v) {
	if (l == r) {
		T[rt].a = v;
		T[rt].b = v;
		return;
	}
	int mid = l + r >> 1;
	if (pos <= mid) modify(ls, l, mid, pos, v);
	else modify(rs, mid + 1, r, pos, v);
	update(rt);
}

node query(int rt, int l, int r, int L, int R) {
	if (L <= l && r <= R) {
		return T[rt];
	}
	int mid = l + r >> 1;
	node res = {0, 0}, tmp = {0, 0}, ans = {0, 0};
	if (L <= mid) ans = res = query(ls, l, mid, L, R);
	if (R > mid) {
		tmp = query(rs, mid + 1, r, L, R);
		if (res.a == 0 && res.b == 0) ans = tmp;
		else ans.a = res.a + res.b * tmp.a, ans.b = res.b * tmp.b;
	}
//	printf("%.10lf %.10lf ", res.a, res.b);
//	printf("%.10lf %.10lf ", tmp.a, tmp.b);
//	printf("%.10lf %.10lf\n", ans.a, ans.b);
	return ans;
}

signed main() {
	n = read(), q = read();
	for (int i = 1; i <= n; ++ i) {
		int x = read(), y = read();
		double p = x * 1.0 / y * 1.0;
		t[i] = (1.0 - p) / p;
//		printf("%.10lf\n", t[i]);
	}
	build(1, 1, n);
//	printf("%.10lf %.10lf\n", T[1].a, T[1].b);
	while (q--) {
		int op = read();
		if (op == 1) {
			int pos = read(), x = read(), y = read();
		double p = x * 1.0 / y * 1.0;
			modify(1, 1, n, pos, (1.0 - p) / p);
		} else {
			int l = read(), r = read();
			double fm = query(1, 1, n, l, r).a;
			printf("%.10lf\n", 1 / (fm + 1.0));
		}
	}
	return 0;
}


#include <bits/stdc++.h>
#define int long long

const int N = 1e5 + 7;

int n, q;
double t[N];

inline int read() {
	int x = 0;
	char ch = getchar();
	while (!isdigit(ch)) ch = getchar();
	while (isdigit(ch)) {
		x = x * 10 + ch - 48;
		ch = getchar();
	}
	return x;
}

#define ls (rt << 1)
#define rs (rt << 1 | 1)

struct node{
	double a, b;
}T[N];

void update(int rt) {
	T[rt].a = T[ls].a + T[ls].b * T[rs].a;
	T[rt].b = T[ls].b * T[rs].b;
}

void build(int rt, int l, int r) {
	if (l == r) {
		T[rt].a = t[l];
		T[rt].b = t[l];
		return;
	}
	int mid = l + r >> 1;
	build(ls, l, mid);
	build(rs, mid + 1, r);
	update(rt);
}

void modify(int rt, int l, int r, int pos, double v) {
	if (l == r) {
		T[rt].a = v;
		T[rt].b = v;
		return;
	}
	int mid = l + r >> 1;
	if (pos <= mid) modify(ls, l, mid, pos, v);
	else modify(rs, mid + 1, r, pos, v);
	update(rt);
}

node query(int rt, int l, int r, int L, int R) {
	if (L <= l && r <= R) {
		return T[rt];
	}
	int mid = l + r >> 1;
	node res = {0, 0}, tmp = {0, 0}, ans = {0, 0};
	if (L <= mid) ans = res = query(ls, l, mid, L, R);
	if (R > mid) {
		tmp = query(rs, mid + 1, r, L, R);
		if (res.a == 0 && res.b == 0) ans = tmp;
		else ans.a = res.a + res.b * tmp.a, ans.b = res.b * tmp.b;
	}
//	printf("%.10lf %.10lf ", res.a, res.b);
//	printf("%.10lf %.10lf ", tmp.a, tmp.b);
//	printf("%.10lf %.10lf\n", ans.a, ans.b);
	return ans;
}

signed main() {
	n = read(), q = read();
	for (int i = 1; i <= n; ++ i) {
		int x = read(), y = read();
		double p = x * 1.0 / y * 1.0;
		t[i] = (1.0 - p) / p;
//		printf("%.10lf\n", t[i]);
	}
	build(1, 1, n);
//	printf("%.10lf %.10lf\n", T[1].a, T[1].b);
	while (q--) {
		int op = read();
		if (op == 1) {
			int pos = read(), x = read(), y = read();
		double p = x * 1.0 / y * 1.0;
			modify(1, 1, n, pos, (1.0 - p) / p);
		} else {
			int l = read(), r = read();
			double fm = query(1, 1, n, l, r).a;
			printf("%.10lf\n", 1 / (fm + 1.0));
		}
	}
	return 0;
}


#include<bits/stdc++.h>
using namespace std;
const int maxn=1E5+5;
int n,m;
double x,y,a[maxn];
struct tree{int l,r;double L,R;}t[maxn*4];
tree merge(tree x,tree y)
{
	tree z;
	z.l=x.l;z.r=y.r;
	z.L=x.L*y.L/(1-(1-y.L)*(1-x.R));
	z.R=x.R*y.R/(1-(1-y.L)*(1-x.R));//不要认为反一反就对了QAQ
	return z;
}
void build(int l,int r,int num)
{
	t[num].l=l,t[num].r=r;
	if(l==r)
	{
		t[num].L=a[l];
		t[num].R=1-a[l];
		return;
	}
	int mid=(l+r)>>1;
	build(l,mid,num*2);build(mid+1,r,num*2+1);
	t[num]=merge(t[num*2],t[num*2+1]);
}
void change(int pos,double val,int num)
{
	if(t[num].l==t[num].r)
	{
		t[num].L=val;
		t[num].R=1-val;
		return;
	}
	int mid=(t[num].l+t[num].r)>>1;
	if(pos<=mid)change(pos,val,num*2);
	else change(pos,val,num*2+1);
	t[num]=merge(t[num*2],t[num*2+1]);
}
tree ask(int L,int R,int num)
{
	if(L<=t[num].l&&t[num].r<=R)return t[num];
	int mid=(t[num].l+t[num].r)>>1;
	if(R<=mid)return ask(L,R,num*2);
	else if(mid<L)return ask(L,R,num*2+1);
	else return merge(ask(L,R,num*2),ask(L,R,num*2+1));
}
int main()
{
	ios::sync_with_stdio(false);
	cin>>n>>m;
	for(int i=1;i<=n;++i)
	{
		cin>>x>>y;
		a[i]=x/y;
	}
	build(1,n,1);
	while(m--)
	{
		int opt,d;
		cin>>opt;
		if(opt==1)
		{
			cin>>d>>x>>y;
			change(d,x/y,1);
		}
		else
		{
			int l,r;
			cin>>l>>r;
			cout<<fixed<<setprecision(8)<<ask(l,r,1).L<<endl;
		}
	}
	return 0;
}


#include<bits/stdc++.h>
using namespace std;
const int maxn=1E5+5;
int n,m;
double x,y,a[maxn];
struct tree{int l,r;double p1,p2;}t[maxn*4];
tree merge(tree x,tree y)
{
	tree z;
	z.l=x.l;z.r=y.r;
	double t=1/(1-x.p2*y.p1);
	z.p1=x.p1+(1-x.p1)*y.p1*(1-x.p2)*t;
	z.p2=y.p2+(1-y.p2)*x.p2*(1-y.p1)*t;
	return z;
}
void build(int l,int r,int num)
{
	t[num].l=l,t[num].r=r;
	if(l==r)
	{
		t[num].p1=1-a[l];
		t[num].p2=a[l];
		return;
	}
	int mid=(l+r)>>1;
	build(l,mid,num*2);build(mid+1,r,num*2+1);
	t[num]=merge(t[num*2],t[num*2+1]);
}
void change(int pos,double val,int num)
{
	if(t[num].l==t[num].r)
	{
		t[num].p1=1-val;
		t[num].p2=val;
		return;
	}
	int mid=(t[num].l+t[num].r)>>1;
	if(pos<=mid)change(pos,val,num*2);
	else change(pos,val,num*2+1);
	t[num]=merge(t[num*2],t[num*2+1]);
}
tree ask(int L,int R,int num)
{
	if(L<=t[num].l&&t[num].r<=R)return t[num];
	int mid=(t[num].l+t[num].r)>>1;
	if(R<=mid)return ask(L,R,num*2);
	else if(mid<L)return ask(L,R,num*2+1);
	else return merge(ask(L,R,num*2),ask(L,R,num*2+1));
}
int main()
{
	ios::sync_with_stdio(false);
	cin>>n>>m;
	for(int i=1;i<=n;++i)
	{
		cin>>x>>y;
		a[i]=x/y;
	}
	build(1,n,1);
	while(m--)
	{
		int opt,d;
		cin>>opt;
		if(opt==1)
		{
			cin>>d>>x>>y;
			change(d,x/y,1);
		}
		else
		{
			int l,r;
			cin>>l>>r;
			cout<<fixed<<setprecision(8)<<1-ask(l,r,1).p1<<endl;
		}
	}
	return 0;
}


#include<bits/stdc++.h>
using namespace std;
const int maxn=1E5+5;
int n,m;
double x,y,a[maxn];
struct tree{int l,r;double L,R;}t[maxn*4];
tree merge(tree x,tree y)
{
	tree z;
	z.l=x.l;z.r=y.r;
	z.L=x.L*y.L/(1-(1-y.L)*(1-x.R));
	z.R=x.R*y.R/(1-(1-y.R)*(1-x.L));
	return z;
}
void build(int l,int r,int num)
{
	t[num].l=l,t[num].r=r;
	if(l==r)
	{
		t[num].L=a[l];
		t[num].R=1-a[l];
		return;
	}
	int mid=(l+r)>>1;
	build(l,mid,num*2);build(mid+1,r,num*2+1);
	t[num]=merge(t[num*2],t[num*2+1]);
}
void change(int pos,double val,int num)
{
	if(t[num].l==t[num].r)
	{
		t[num].L=val;
		t[num].R=1-val;
		return;
	}
	int mid=(t[num].l+t[num].r)>>1;
	if(pos<=mid)change(pos,val,num*2);
	else change(pos,val,num*2+1);
	t[num]=merge(t[num*2],t[num*2+1]);
}
tree ask(int L,int R,int num)
{
	if(L<=t[num].l&&t[num].r<=R)return t[num];
	int mid=(t[num].l+t[num].r)>>1;
	if(R<=mid)return ask(L,R,num*2);
	else if(mid<L)return ask(L,R,num*2+1);
	else return merge(ask(L,R,num*2),ask(L,R,num*2+1));
}
int main()
{
	ios::sync_with_stdio(false);
	cin>>n>>m;
	for(int i=1;i<=n;++i)
	{
		cin>>x>>y;
		a[i]=x/y;
	}
	build(1,n,1);
	while(m--)
	{
		int opt,d;
		cin>>opt;
		if(opt==1)
		{
			cin>>d>>x>>y;
			change(d,x/y,1);
		}
		else
		{
			int l,r;
			cin>>l>>r;
			cout<<fixed<<setprecision(8)<<ask(l,r,1).L<<endl;
		}
	}
	return 0;
}


#include <iostream>
#include <vector>
using namespace std;

// vector<double> prob;
typedef pair<double, double> dd;

struct Node{
	double a=0.5,b=0.5;
	int left;
	int right;
};

vector<Node> v;

void init(int l, int r, int x){
	v[x].left = l;
	v[x].right = r;
	if(l!=r){
		int mid = (l+r)/2;
		init(l,mid,2*x);
		init(mid+1,r,2*x+1);
	}
}

void set_prob(int n, int val, double prob){
	if(val > v[n].right || val < v[n].left) return;
	if(v[n].right == v[n].left){
		v[n].a = prob;
		v[n].b = (1-prob);
		// cout << "Val set " << v[n].right << " " << prob << endl;
		return;
	}
	set_prob(2*n, val, prob);
	set_prob(2*n+1, val, prob);
	v[n].a = v[2*n].a * v[2*n+1].a / (1 - (1 - v[2*n].b)*(1 - v[2*n+1].a));
	v[n].b = v[2*n].b * v[2*n+1].b / (1 - (1 - v[2*n].b)*(1 - v[2*n+1].a));
}

pair<double, double> search(int n, int l, int r){
	if(v[n].right < l || r < v[n].left) return make_pair(1,1);
	if(l <= v[n].left && v[n].right <= r) return make_pair(v[n].a, v[n].b);
	auto p1 = search(2*n, l, r);
	auto p2 = search(2*n+1, l, r);
	double denom = 1 - (1 - p2.first)*(1 - p1.second);
	return make_pair(p1.first*p2.first/denom, p1.second*p2.second/denom);
}

void show_prob(int n){
	if(v[n].left == v[n].right){
		cout << "Base " << v[n].left << " " << v[n].a << " " << v[n].b <<  endl;
		return;
	}
	show_prob(2*n);
	show_prob(2*n+1);
	cout << v[n].left << " " << v[n].right << " " << v[n].a << " " << v[n].b << endl;
}

int main(int argc, char const *argv[])
{
	// int n, q, type, temp, l, r;
	// long long a, b;
	// scanf("%d %d", &n, &q);
	// prob = vector<double>(n+1);
	// for(int i=1; i<=n; ++i){
	// 	cin >> a >> b;
	// 	prob[i] = 1.0*a/b;
	// }
	// for(int i=0; i<q; ++i){
	// 	cin >> type;
	// 	if(type==1){
	// 		cin >> temp >> a >> b;
	// 		prob[temp] = 1.0*a/b;
	// 	}else{
	// 		cin >> l >> r;
	// 		double x = prob[r];
	// 		for(int j=r-1; j>=l; --j){
	// 			x = prob[j]*x/(1-prob[j]*(1-x));
	// 		}
	// 		cout << x << endl;
	// 	}
	// }
	// return 0;

	int n, q, type, temp, l, r;
	long long a, b;
	scanf("%d %d", &n, &q);
	v = vector<Node>(4*n+2);
	init(1,n,1);
	for(int i=1; i<=n; ++i){
		cin >> a >> b;
		set_prob(1, i, 1.0*a/b);
	}
	// show_prob(1);
	for(int i=0; i<q; ++i){
		cin >> type;
		if(type==1){
			cin >> temp >> a >> b;
			// prob[temp] = 1.0*a/b;
			set_prob(1, temp, 1.0*a/b);
		}else{
			cin >> l >> r;
			cout << search(1, l, r).first << endl;
		}
	}
}


#include <iostream>
#include <vector>
using namespace std;

vector<double> prob;

int main(int argc, char const *argv[])
{
	int n, q, type, temp, l, r;
	long long a, b;
	scanf("%d %d", &n, &q);
	prob = vector<double>(n+1);
	for(int i=1; i<=n; ++i){
		cin >> a >> b;
		prob[i] = 1.0*a/b;
	}
	for(int i=0; i<q; ++i){
		cin >> type;
		if(type==1){
			cin >> temp >> a >> b;
			prob[temp] = 1.0*a/b;
		}else{
			cin >> l >> r;
			double x = prob[r];
			for(int j=r-1; j>=l; --j){
				x = prob[j]*x/(1-prob[j]*(1-x));
			}
			cout << x << endl;
		}
	}
	return 0;
}


#include<bits/stdc++.h>

const int N = 100010;

__float128 p[N], pre[N], pre_pro[N];
int n, q, m;

__float128 calc(int l, int r){
	__float128 prod = 1, ret = 0;
	if (l / m == r / m){
		for (int i = l; i <= r; ++ i){
			ret += prod;
			prod *= p[i];
		}
		return ret + prod;
	}
	for (int i = l; i < (l / m + 1) * m; ++ i){
		ret += prod;
		prod *= p[i];
	}
	for (int i = l / m + 1; i < r / m; ++ i){
		ret += pre[i] * prod;
		prod *= pre_pro[i];
	}
	for (int i = r / m * m; i <= r; ++ i){
		ret += prod;
		prod *= p[i];
	}
	return ret + prod;
}

int main(){
	scanf("%d%d", &n, &q);
	m = sqrt(n);
	for (int i = 1, a, b; i <= n; ++ i){
		scanf("%d%d", &a, &b);
		p[i] = 1.0 * a / b;
		p[i] = 1.0 * (b - a) / a;
	}
	for (int i = 0; i < n; i += m){
		__float128 prod = 1;
		pre_pro[i / m] = 1;
		for (int j = i; j < i + m; ++ j){
			pre[i / m] += prod;
			pre_pro[i / m] *= p[j];
			prod *= p[j];
		}
	}
	while (q --){
		int type;
		scanf("%d", &type);
		if (type == 1){
			int sit, a, b;
			scanf("%d%d%d", &sit, &a, &b);
			p[sit] = 1.0 * (b - a) / a;
			int i = sit / m * m;
			__float128 prod = 1;
			pre[i / m] = 0;
			pre_pro[i / m] = 1;
			for (int j = i; j < i + m; ++ j){
				pre[i / m] += prod;
				prod *= p[j];
				pre_pro[i / m] *= p[j];
			}
			continue;
		}
		int l, r;
		scanf("%d%d", &l, &r);
		if (l == r){
			printf("%.10lf\n", (double) (1 / (1 + p[l])));
			continue;
		}
		if (l == r - 1){
			printf("%.10lf\n", (double) (1 / ((1 + p[l]) * (1 + p[r]) - p[r])));
			continue;
		}
		__float128 coe1 = calc(l, r - 1), coe2 = calc(l, r - 2), x = 1 / (1 + p[r]);
		printf("%.10lf\n", (double) (x / (coe1 - (1 - x) * coe2)));
	}
	return 0;

}


#include<bits/stdc++.h>
#define double long double

const int N = 100010;

double p[N], pre[N], pre_pro[N];
int n, q, m;

double calc(int l, int r){
	double prod = 1, ret = 0;
	if (l / m == r / m){
		for (int i = l; i <= r; ++ i){
			ret += prod;
			prod *= p[i];
		}
		return ret + prod;
	}
	for (int i = l; i < (l / m + 1) * m; ++ i){
		ret += prod;
		prod *= p[i];
	}
	for (int i = l / m + 1; i < r / m; ++ i){
		ret += pre[i] * prod;
		prod *= pre_pro[i];
	}
	for (int i = r / m * m; i <= r; ++ i){
		ret += prod;
		prod *= p[i];
	}
	return ret + prod;
}

int main(){
	scanf("%d%d", &n, &q);
	m = sqrt(n);
	pre_pro[0] = 1;
	for (int i = 1, a, b; i <= n; ++ i){
		scanf("%d%d", &a, &b);
		p[i] = 1.0 * a / b;
		p[i] = 1.0 * (b - a) / a;
		pre_pro[i] = pre_pro[i - 1] * p[i];
	}
	for (int i = 0; i < n; i += m){
		double prod = 1;
		pre_pro[i] = 1;
		for (int j = i; j < i + m; ++ j){
			pre[i] += prod;
			pre_pro[i] *= p[j];
			prod *= p[j];
		}
	}
	while (q --){
		int type;
		scanf("%d", &type);
		if (type == 1){
			int sit, a, b;
			scanf("%d%d%d", &sit, &a, &b);
			p[sit] = 1.0 * (b - a) / a;
			int i = sit / m * m;
			double prod = 1;
			pre[i] = 0;
			pre_pro[i] = 1;
			for (int j = i; j < i + m; ++ j){
				pre[i] += prod;
				prod *= p[j];
				pre_pro[i] *= p[j];
			}
			continue;
		}
		int l, r;
		scanf("%d%d", &l, &r);
		if (l == r){
			printf("%.10lf\n", 1 / (1 + p[l]));
			continue;
		}
		if (l == r - 1){
			printf("%.10lf\n", 1 / ((1 + p[l]) * (1 + p[r]) - p[r]));
			continue;
		}
		double coe1 = calc(l, r - 1), coe2 = calc(l, r - 2), x = 1 / (1 + p[r]);
		printf("%.10lf\n", x / (coe1 - (1 - x) * coe2));
	}
	return 0;

}


#include<bits/stdc++.h>

const int MAX = 1 << 17;
const double eps = 1e-9;

struct segment{
	std::pair <double, double> value;
	int left, right;
};

segment seg[MAX << 1];
int n, q;
double p[MAX];

void build(){
	for (int i = MAX; i < MAX + n; ++ i){
		seg[i] = {{p[i - MAX], p[i - MAX]}, i - MAX, i - MAX};
	}
	for (int i = MAX + n; i < MAX << 1; ++ i){
		seg[i] = {{0, 1}, i - MAX, i - MAX};
	}
	for (int i = MAX - 1; i; -- i){
		std::pair <double, double> p1 = seg[i << 1].value, p2 = seg[(i << 1) + 1].value;
		seg[i] = {{p1.first * p2.first / (1 + p1.second * (p2.first - 1)),
				p2.second + (1 - p2.second) * p1.second * p2.first / (1 + p1.second * (p2.first - 1))},
				seg[i << 1].left, seg[(i << 1) + 1].right};
	}
}

void add(int i){
	i += MAX;
	seg[i] = {{p[i - MAX], p[i- MAX]}, i - MAX, i - MAX};
	for (i >>= 1; i; i >>= 1){
		std::pair <double, double> p1 = seg[i << 1].value, p2 = seg[(i << 1) + 1].value;
		seg[i].value = {p1.first * p2.first / (1 + p1.second * (p2.first - 1)),
				p2.second + (1 - p2.second) * p1.second * p2.first / (1 + p1.second * (p2.first - 1))};
	}
}

std::pair <double, double> query(int left, int right, int sit){
	if (left == seg[sit].left && right == seg[sit].right){
		return seg[sit].value;
	}
	if (left >= seg[(sit << 1) + 1].left){
		return query(left, right, (sit << 1) + 1);
	}
	if (right <= seg[sit << 1].right){
		return query(left, right, sit << 1);
	}
	std::pair <double, double> p1 = query(left, seg[sit << 1].right, sit << 1), p2 = query(seg[(sit << 1) + 1].left, right, (sit << 1) + 1);
	return {p1.first * p2.first / (1 + p1.second * (p2.first - 1)),
			p2.second + (1 - p2.second) * p1.second * p2.first / (1 + p1.second * (p2.first - 1))};
}

int main(){
	scanf("%d%d", &n, &q);
	for (int i = 0, a, b; i < n; ++ i){
		scanf("%d%d", &a, &b);
		p[i] = 1.0 * a / b;
	}
	build();
	while (q --){
		int type;
		scanf("%d", &type);
		if (type == 1){
			int sit, a, b;
			scanf("%d%d%d", &sit, &a, &b);
			-- sit;
			p[sit] = 1.0 * a / b;
			add(sit);
			continue;
		}
		int l, r;
		scanf("%d%d", &l, &r);
		-- l, -- r;
		/*if (l == r){
			printf("%.10lf\n", 1 / (1 + p[l]));
			continue;
		}
		if (l == r - 1){
			printf("%.10lf\n", 1 / ((1 + p[l]) * (1 + p[r]) - p[r]));
			continue;
		}*/
		printf("%.10lf\n", query(l, r, 1).first);
	}
	return 0;
}


#include<bits/stdc++.h>

const int N = 100010;

double p[N], pre[N], pre_pro[N];
int n, q, m;

double calc(int l, int r){
	double prod = 1, ret = 0;
	if (l / m == r / m){
		for (int i = l; i <= r; ++ i){
			ret += prod;
			prod *= p[i];
		}
		return ret + prod;
	}
	for (int i = l; i < (l / m + 1) * m; ++ i){
		ret += prod;
		prod *= p[i];
	}
	for (int i = l / m + 1; i < r / m; ++ i){
		ret += pre[i];
		prod *= pre_pro[i];
	}
	for (int i = r / m * m; i <= r; ++ i){
		ret += prod;
		prod *= p[i];
	}
	return ret + prod;
}
int main(){
	scanf("%d%d", &n, &q);
	m = sqrt(n);
	pre_pro[0] = 1;
	for (int i = 1, a, b; i <= n; ++ i){
		scanf("%d%d", &a, &b);
		p[i] = 1.0 * a / b;
		p[i] = 1.0 * (b - a) / a;
		pre_pro[i] = pre_pro[i - 1] * p[i];
	}
	for (int i = 0; i < n; i += m){
		double prod = 1;
		pre_pro[i] = 1;
		for (int j = i; j < i + m; ++ j){
			pre[i] += p[j];
			pre_pro[i] *= p[j];
			prod *= p[j];
		}
	}
	while (q --){
		int type;
		scanf("%d", &type);
		if (type == 1){
			int sit, a, b;
			scanf("%d%d%d", &sit, &a, &b);
			p[sit] = 1.0 * (b - a) / a;
			int i = sit / m * m;
			double prod = 1;
			pre[i] = 0;
			pre_pro[i] = 1;
			for (int j = i; j < i + m; ++ j){
				pre[i] += p[j];
				prod *= p[j];
				pre_pro[i] *= p[j];
			}
			continue;
		}
		int l, r;
		scanf("%d%d", &l, &r);
		if (l == r){
			printf("%.10lf\n", 1 / (1 + p[l]));
			continue;
		}
		if (l == r - 1){
			printf("%.10lf\n", 1 / ((1 + p[l]) * (1 + p[r]) - p[r]));
			continue;
		}
		double coe1 = calc(l, r - 1), coe2 = calc(l, r - 2), x = 1 / (1 + p[r]);
		printf("%.10lf\n", x / (coe1 - (1 - x) * coe2));
	}
	return 0;

}


#include<bits/stdc++.h>

const int N = 100010;

double p[N], pre[N], pre_pro[N];
int n, q, m;

double calc(int l, int r){
	double prod = 1, ret = 0;
	if (l / m == r / m){
		for (int i = l; i <= r; ++ i){
			ret += prod;
			prod *= p[i];
		}
		return ret + prod;
	}
	for (int i = l; i < (l / m + 1) * m; ++ i){
		ret += prod;
		prod *= p[i];
	}
	for (int i = l / m + 1; i < r / m - 1; ++ i){
		ret += pre[i] * prod;
		prod *= pre_pro[i];
	}
	for (int i = r / m * m; i <= r; ++ i){
		ret += prod;
		prod *= p[i];
	}
	return ret + prod;
}

int main(){
	scanf("%d%d", &n, &q);
	m = sqrt(n);
	pre_pro[0] = 1;
	for (int i = 1, a, b; i <= n; ++ i){
		scanf("%d%d", &a, &b);
		p[i] = 1.0 * a / b;
		p[i] = 1.0 * (b - a) / a;
		pre_pro[i] = pre_pro[i - 1] * p[i];
	}
	for (int i = 0; i < n; i += m){
		double prod = 1;
		pre_pro[i] = 1;
		for (int j = i; j < i + m; ++ j){
			pre[i] += prod;
			pre_pro[i] *= p[j];
			prod *= p[j];
		}
	}
	while (q --){
		int type;
		scanf("%d", &type);
		if (type == 1){
			int sit, a, b;
			scanf("%d%d%d", &sit, &a, &b);
			p[sit] = 1.0 * (b - a) / a;
			int i = sit / m * m;
			double prod = 1;
			pre[i] = 0;
			pre_pro[i] = 1;
			for (int j = i; j < i + m; ++ j){
				pre[i] += prod;
				prod *= p[j];
				pre_pro[i] *= p[j];
			}
			continue;
		}
		int l, r;
		scanf("%d%d", &l, &r);
		if (l == r){
			printf("%.10lf\n", 1 / (1 + p[l]));
			continue;
		}
		if (l == r - 1){
			printf("%.10lf\n", 1 / ((1 + p[l]) * (1 + p[r]) - p[r]));
			continue;
		}
		double coe1 = calc(l, r - 1), coe2 = calc(l, r - 2), x = 1 / (1 + p[r]);
		printf("%.10lf\n", x / (coe1 - (1 - x) * coe2));
	}
	return 0;

}


#include<bits/stdc++.h>

const int MAX = 1 << 17;
const double eps = 1e-9;

struct segment{
	std::pair <double, double> value;
	int left, right;
};

segment seg[MAX << 1];
int n, q;
double p[MAX];

void build(){
	for (int i = MAX; i < MAX + n; ++ i){
		seg[i] = {{p[i - MAX], p[i - MAX]}, i - MAX, i - MAX};
	}
	for (int i = MAX + n; i < MAX << 1; ++ i){
		seg[i] = {{0, 1}, i - MAX, i - MAX};
	}
	for (int i = MAX - 1; i; -- i){
		std::pair <double, double> p1 = seg[i << 1].value, p2 = seg[(i << 1) + 1].value;
		seg[i] = {{p1.first + p1.second * p2.first, p1.second * p2.second}, seg[i << 1].left, seg[(i << 1) + 1].right};
	}
}

void add(int i){
	i += MAX;
	seg[i] = {{p[i - MAX], p[i- MAX]}, i - MAX, i - MAX};
	for (i >>= 1; i; i >>= 1){
		std::pair <double, double> p1 = seg[i << 1].value, p2 = seg[(i << 1) + 1].value;
		seg[i].value = {p1.first + p1.second * p2.first, p1.second * p2.second};
	}
}

std::pair <double, double> query(int left, int right, int sit){
	if (left == seg[sit].left && right == seg[sit].right){
		return seg[sit].value;
	}
	if (left >= seg[(sit << 1) + 1].left){
		return query(left, right, (sit << 1) + 1);
	}
	if (right <= seg[sit << 1].right){
		return query(left, right, sit << 1);
	}
	std::pair <double, double> p1 = query(left, seg[sit << 1].right, sit << 1), p2 = query(seg[(sit << 1) + 1].left, right, (sit << 1) + 1);
	return {p1.first + p1.second * p2.first, p1.second * p2.second};
}

int main(){
	scanf("%d%d", &n, &q);
	for (int i = 0, a, b; i < n; ++ i){
		scanf("%d%d", &a, &b);
		p[i] = 1.0 * (b - a) / a;
	}
	build();
	while (q --){
		int type;
		scanf("%d", &type);
		if (type == 1){
			int sit, a, b;
			scanf("%d%d%d", &sit, &a, &b);
			-- sit;
			p[sit] = 1.0 * (b - a) / a;
			add(sit);
			continue;
		}
		int l, r;
		scanf("%d%d", &l, &r);
		-- l, -- r;
		if (l == r){
			printf("%.10lf\n", 1 / (1 + p[l]));
			continue;
		}
		if (l == r - 1){
			printf("%.10lf\n", 1 / ((1 + p[l]) * (1 + p[r]) - p[r]));
			continue;
		}
		double coe1 = query(l, r - 1, 1).first + 1, coe2 = query(l, r - 2, 1).first + 1, x = 1 / (1 + p[r]);
		double div = coe1 - (1 - x) * coe2;
		if (std::abs(div) < eps){
			printf("%.10lf", 0.0);
			continue;
		}
		printf("%.10lf\n", x / div);
	}
	return 0;
}


#include<bits/stdc++.h>

const int N = 100010;

double p[N], pre[N], pre_pro[N];
int n, q, m;

double calc(int l, int r){
	double prod = 1, ret = 0;
	if (l / m == r / m){
		for (int i = l; i <= r; ++ i){
			ret += prod;
			prod *= p[i];
		}
		return ret + prod;
	}
	for (int i = l; i < (l / m + 1) * m; ++ i){
		ret += prod;
		prod *= p[i];
	}
	for (int i = l / m + 1; i < r / m; ++ i){
		ret += pre[i] * prod;
		prod *= pre_pro[i];
	}
	for (int i = r / m * m; i <= r; ++ i){
		ret += prod;
		prod *= p[i];
	}
	return ret + prod;
}

int main(){
	scanf("%d%d", &n, &q);
	m = sqrt(n);
	for (int i = 1, a, b; i <= n; ++ i){
		scanf("%d%d", &a, &b);
		p[i] = 1.0 * a / b;
		p[i] = 1.0 * (b - a) / a;
	}
	for (int i = 0; i < n; i += m){
		double prod = 1;
		pre_pro[i / m] = 1;
		for (int j = i; j < i + m; ++ j){
			pre[i / m] += prod;
			pre_pro[i / m] *= p[j];
			prod *= p[j];
		}
	}
	while (q --){
		int type;
		scanf("%d", &type);
		if (type == 1){
			int sit, a, b;
			scanf("%d%d%d", &sit, &a, &b);
			p[sit] = 1.0 * (b - a) / a;
			int i = sit / m * m;
			double prod = 1;
			pre[i / m] = 0;
			pre_pro[i / m] = 1;
			for (int j = i; j < i + m; ++ j){
				pre[i / m] += prod;
				prod *= p[j];
				pre_pro[i / m] *= p[j];
			}
			continue;
		}
		int l, r;
		scanf("%d%d", &l, &r);
		if (l == r){
			printf("%.10lf\n", 1 / (1 + p[l]));
			continue;
		}
		if (l == r - 1){
			printf("%.10lf\n", 1 / ((1 + p[l]) * (1 + p[r]) - p[r]));
			continue;
		}
		double coe1 = calc(l, r - 1), coe2 = calc(l, r - 2), x = 1 / (1 + p[r]);
		printf("%.10lf\n", x / (coe1 - (1 - x) * coe2));
	}
	return 0;

}


#include<bits/stdc++.h>

const int N = 100010;

double p[N], pre[N], pre_pro[N];
int n, q, m;

double calc(int l, int r){
	double prod = 1, ret = 0;
	if (l / m == r / m){
		for (int i = l; i <= r; ++ i){
			ret += prod;
			prod *= p[i];
		}
		return ret + prod;
	}
	for (int i = l; i < (l / m + 1) * m; ++ i){
		ret += prod;
		prod *= p[i];
	}
	for (int i = l / m + 1; i < r / m; ++ i){
		ret += pre[i] * prod;
		prod *= pre_pro[i];
	}
	for (int i = r / m * m; i <= r; ++ i){
		ret += prod;
		prod *= p[i];
	}
	return ret + prod;
}

int main(){
	scanf("%d%d", &n, &q);
	m = sqrt(n);
	for (int i = 1, a, b; i <= n; ++ i){
		scanf("%d%d", &a, &b);
		p[i] = 1.0 * a / b;
		p[i] = 1.0 * (b - a) / a;
	}
	for (int i = 0; i < n; i += m){
		double prod = 1;
		pre_pro[i / m] = 1;
		for (int j = i; j < i + m; ++ j){
			pre[i / m] += prod;
			pre_pro[i / m] *= p[j];
			prod *= p[j];
		}
	}
	while (q --){
		int type;
		scanf("%d", &type);
		if (type == 1){
			int sit, a, b;
			scanf("%d%d%d", &sit, &a, &b);
			p[sit] = 1.0 * (b - a) / a;
			int i = sit / m * m;
			double prod = 1;
			pre[i] = 0;
			pre_pro[i] = 1;
			for (int j = i; j < i + m; ++ j){
				pre[i] += prod;
				prod *= p[j];
				pre_pro[i] *= p[j];
			}
			continue;
		}
		int l, r;
		scanf("%d%d", &l, &r);
		if (l == r){
			printf("%.10lf\n", 1 / (1 + p[l]));
			continue;
		}
		if (l == r - 1){
			printf("%.10lf\n", 1 / ((1 + p[l]) * (1 + p[r]) - p[r]));
			continue;
		}
		double coe1 = calc(l, r - 1), coe2 = calc(l, r - 2), x = 1 / (1 + p[r]);
		printf("%.10lf\n", x / (coe1 - (1 - x) * coe2));
	}
	return 0;

}


#include<bits/stdc++.h>

const int N = 100010;

double p[N], pre[N], pre_pro[N];
int n, q, m;

double calc(int l, int r){
	double prod = 1, ret = 0;
	if (l / m == r / m){
		for (int i = l; i <= r; ++ i){
			ret += prod;
			prod *= p[i];
		}
		return ret + prod;
	}
	for (int i = l; i < (l / m + 1) * m; ++ i){
		ret += prod;
		prod *= p[i];
	}
	for (int i = l / m + 1; i < r / m; ++ i){
		ret += pre[i];
		prod *= pre_pro[i * m] / pre_pro[(i - 1) * m];
	}
	for (int i = r / m * m; i <= r; ++ i){
		ret += prod;
		prod *= p[i];
	}
	return ret + prod;
}
int main(){
	scanf("%d%d", &n, &q);
	m = sqrt(n);
	pre_pro[0] = 1;
	for (int i = 1, a, b; i <= n; ++ i){
		scanf("%d%d", &a, &b);
		p[i] = 1.0 * a / b;
		p[i] = 1.0 * (b - a) / a;
		pre_pro[i] = pre_pro[i - 1] * p[i];
	}
	for (int i = 0; i < n; i += m){
		double prod = 1;
		for (int j = i; j < i + m; ++ j){
			pre[i] += p[j];
			prod *= p[j];
		}
	}
	while (q --){
		int type;
		scanf("%d", &type);
		if (type == 1){
			int sit, a, b;
			scanf("%d%d%d", &sit, &a, &b);
			p[sit] = 1.0 * (b - a) / a;
			int i = sit / m * m;
			double prod = 1;
			pre[i] = 0;
			for (int j = i; j < i + m; ++ j){
				pre[i] += p[j];
				prod *= p[j];
			}
			continue;
		}
		int l, r;
		scanf("%d%d", &l, &r);
		if (l == r){
			printf("%.10lf\n", 1 / (1 + p[l]));
			continue;
		}
		if (l == r - 1){
			printf("%.10lf\n", 1 / (2 + p[l] + p[r]));
			continue;
		}
		double coe1 = calc(l, r - 1), coe2 = calc(l, r - 2), x = 1 / (1 + p[r]);
		printf("%.10lf\n", x / (coe1 - (1 - x) * coe2));
	}
	return 0;

}


#include<bits/stdc++.h>

const int N = 100010;

double p[N], pre[N], pre_pro[N];
int n, q, m;

double calc(int l, int r){
	double prod = 1, ret = 0;
	if (l / m == r / m){
		for (int i = l; i <= r; ++ i){
			ret += prod;
			prod *= p[i];
		}
		return ret + prod;
	}
	for (int i = l; i < (l / m + 1) * m; ++ i){
		ret += prod;
		prod *= p[i];
	}
	for (int i = l / m + 1; i < r / m; ++ i){
		ret += pre[i] * prod;
		prod *= pre_pro[i];
	}
	for (int i = r / m * m; i <= r; ++ i){
		ret += prod;
		prod *= p[i];
	}
	return ret + prod;
}

int main(){
	scanf("%d%d", &n, &q);
	m = sqrt(n);
	pre_pro[0] = 1;
	for (int i = 1, a, b; i <= n; ++ i){
		scanf("%d%d", &a, &b);
		p[i] = 1.0 * a / b;
		p[i] = 1.0 * (b - a) / a;
		pre_pro[i] = pre_pro[i - 1] * p[i];
	}
	for (int i = 0; i < n; i += m){
		double prod = 1;
		pre_pro[i] = 1;
		for (int j = i; j < i + m; ++ j){
			pre[i] += prod;
			pre_pro[i] *= p[j];
			prod *= p[j];
		}
	}
	while (q --){
		int type;
		scanf("%d", &type);
		if (type == 1){
			int sit, a, b;
			scanf("%d%d%d", &sit, &a, &b);
			p[sit] = 1.0 * (b - a) / a;
			int i = sit / m * m;
			double prod = 1;
			pre[i] = 0;
			pre_pro[i] = 1;
			for (int j = i; j < i + m; ++ j){
				pre[i] += prod;
				prod *= p[j];
				pre_pro[i] *= p[j];
			}
			continue;
		}
		int l, r;
		scanf("%d%d", &l, &r);
		if (l == r){
			printf("%.10lf\n", 1 / (1 + p[l]));
			continue;
		}
		if (l == r - 1){
			printf("%.10lf\n", 1 / ((1 + p[l]) * (1 + p[r]) - p[r]));
			continue;
		}
		double coe1 = calc(l, r - 1), coe2 = calc(l, r - 2), x = 1 / (1 + p[r]);
		printf("%.10lf\n", x / (coe1 - (1 - x) * coe2));
	}
	return 0;

}


#include<bits/stdc++.h>

const int MAX = 1 << 17;

struct segment{
	std::pair <double, double> value;
	int left, right;
};

segment seg[MAX << 1];
int n, q;
double p[MAX];

void build(){
	for (int i = MAX; i < MAX + n; ++ i){
		seg[i] = {{p[i - MAX], p[i - MAX]}, i - MAX, i - MAX};
	}
	for (int i = MAX + n; i < MAX << 1; ++ i){
		seg[i] = {{0, 1}, i - MAX, i - MAX};
	}
	for (int i = MAX - 1; i; -- i){
		std::pair <double, double> p1 = seg[i << 1].value, p2 = seg[(i << 1) + 1].value;
		seg[i] = {{p1.first + p1.second * p2.first, p1.second * p2.second}, seg[i << 1].left, seg[(i << 1) + 1].right};
	}
}

void add(int i){
	i += MAX;
	seg[i] = {{p[i - MAX], p[i- MAX]}, i - MAX, i - MAX};
	for (i >>= 1; i; i >>= 1){
		std::pair <double, double> p1 = seg[i << 1].value, p2 = seg[(i << 1) + 1].value;
		seg[i].value = {p1.first + p1.second * p2.first, p1.second * p2.second};
	}
}

std::pair <double, double> query(int left, int right, int sit){
	if (left == seg[sit].left && right == seg[sit].right){
		return seg[sit].value;
	}
	if (left >= seg[(sit << 1) + 1].left){
		return query(left, right, (sit << 1) + 1);
	}
	if (right <= seg[sit << 1].right){
		return query(left, right, sit << 1);
	}
	std::pair <double, double> p1 = query(left, seg[sit << 1].right, sit << 1), p2 = query(seg[(sit << 1) + 1].left, right, (sit << 1) + 1);
	return {p1.first + p1.second * p2.first, p1.second * p2.second};
}

int main(){
	scanf("%d%d", &n, &q);
	for (int i = 0, a, b; i < n; ++ i){
		scanf("%d%d", &a, &b);
		p[i] = 1.0 * (b - a) / a;
	}
	build();
	while (q --){
		int type;
		scanf("%d", &type);
		if (type == 1){
			int sit, a, b;
			scanf("%d%d%d", &sit, &a, &b);
			-- sit;
			p[sit] = 1.0 * (b - a) / a;
			add(sit);
			continue;
		}
		int l, r;
		scanf("%d%d", &l, &r);
		-- l, -- r;
		if (l == r){
			printf("%.10lf\n", 1 / (1 + p[l]));
			continue;
		}
		if (l == r - 1){
			printf("%.10lf\n", 1 / ((1 + p[l]) * (1 + p[r]) - p[r]));
			continue;
		}
		double coe1 = query(l, r - 1, 1).first + 1, coe2 = query(l, r - 2, 1).first + 1, x = 1 / (1 + p[r]);
		printf("%.10lf\n", x / (coe1 - (1 - x) * coe2));
	}
	return 0;
}


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

typedef float rl;

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

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

const int MX=100*1000+99;

struct seg_tree
{
    node V[4*MX];

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

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

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

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

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

        return ans;
    }
};

seg_tree T;

int n, q;
rl U[MX];

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

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

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

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

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

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

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

            rl res;
            if(ans.B<1E30) res=1.0/(1.0+ans.B);
            else           res=0.0;
            printf("%f\n", res);
        }
    }

	return 0;
}


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

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

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

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

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

const int MX=100*1000+99;

struct seg_tree
{
    vector<node> V;

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

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

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

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

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

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

    node query(int no, int L, int R, int qL, int qR)
    {
       // printf("%d %d %d %d %d\n", no, L, R, qL, qR);

        //assert(L<=qL && qR<=R);
        //if(qL>qR) return identity;
        if(L==R) return V[no];

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

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

        return ans;
    }
};

seg_tree T;

int n, q;
rl U[MX];

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

    cin >> n >> q;

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

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

    cout << setprecision(6) << fixed;

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

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

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

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

	return 0;
}


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

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

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

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

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

const int MX=100*1000+99;

struct seg_tree
{
    vector<node> V;

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

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

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

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

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

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

    node query(int no, int L, int R, int qL, int qR)
    {
       // printf("%d %d %d %d %d\n", no, L, R, qL, qR);

        assert(L<=qL && qR<=R);
        if(qL>qR) return identity;
        if(L==R) return V[no];

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

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

        return ans;
    }
};

seg_tree T;

int n, q;
rl U[MX];

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

    cin >> n >> q;

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

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

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

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

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

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

	return 0;
}


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

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

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

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

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

const int MX=100*1000+99;

struct seg_tree
{
    vector<node> V;

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

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

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

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

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

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

    node query(int no, int L, int R, int qL, int qR)
    {
       // printf("%d %d %d %d %d\n", no, L, R, qL, qR);

        assert(L<=qL && qR<=R);
        if(qL>qR) return identity;
        if(L==R) return V[no];

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

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

        return ans;
    }
};

seg_tree T;

int n, q;
rl U[MX];

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

    cin >> n >> q;

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

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

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

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

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

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

	return 0;
}


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

typedef float rl;

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

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

const int MX=100*1000+99;

struct seg_tree
{
    node V[4*MX];

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

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

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

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

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

        return ans;
    }
};

seg_tree T;

int n, q;
rl U[MX];

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

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

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

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

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

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

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

            rl res;
            if(ans.B<1E30) res=1.0/(1.0+ans.B);
            else           res=0.0;
            printf("%f\n", res);
        }
    }

	return 0;
}


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

typedef float rl;

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

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

const int MX=100*1000+99;

struct seg_tree
{
    node V[4*MX];

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

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

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

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

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

        return ans;
    }
};

seg_tree T;

int n, q;
rl U[MX];

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

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

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

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

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

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

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

            rl res;
            if(ans.B<1E30) res=1.0/(1.0+ans.B);
            else           res=0.0;
            printf("%f\n", res);
        }
    }

	return 0;
}