/*
区间修改 区间查询 可以用线段树搞
但是一般的标记下放对这个题好像不合适
只能改叶子 然后更新父亲(虽然跑的有点慢)
小优化:如果某个点是1 就不用再开方了
所以搞一个f[i]标记 i 这个点还需不需要处理下去
注意用longlong 还有就是数组开大
*/
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#define LL long long
#define maxn 500010
using namespace std;
LL n,m,num,x,y,z;
LL a[maxn],f[maxn];
struct node
{
LL o;
LL l,r;
LL lc,rc;
LL sum;
}t[maxn*2];
LL init()
{
LL x=0;
char s;
bool f=0;
s=getchar();
while(s<'0'||s>'9')
{
if(s=='-')f=1;
s=getchar();
}
while(s>='0'&&s<='9')
{
x=x*10+s-'0';
s=getchar();
}
if(f==0)return x;
else return -x;
}
void Build(LL ll,LL rr)
{
LL k=++num;
t[k].o=k;
t[k].l=ll;t[k].r=rr;
if(ll!=rr-1)
{
t[k].lc=num+1;
Build(ll,(ll+rr)/2);
t[k].rc=num+1;
Build((ll+rr)/2,rr);
t[k].sum=t[t[k].lc].sum+t[t[k].rc].sum;
}
else t[k].sum=a[ll];
}
void update(LL k,LL ll,LL rr)
{
if(f[k])return;//如果是1 说明儿子(如果有的话)要么是1 要么是0 不需要处理 直接返回
if(ll==rr-1)
{
t[k].sum=sqrt(t[k].sum);
if(t[k].sum==1)f[k]=1;
return;
}
LL mid=(ll+rr)/2;
if(y<mid)update(t[k].lc,ll,(ll+rr)/2);
if(z>=mid)update(t[k].rc,(ll+rr)/2,rr);
t[k].sum=t[t[k].lc].sum+t[t[k].rc].sum;
f[k]=f[t[k].lc]&&f[t[k].rc];//如果左右儿子都是1 那么父亲点也不用更新了.
}
LL find(LL k,LL ll,LL rr)
{
if(ll<=t[k].l&&rr>=t[k].r)return t[k].sum;
LL ans=0;
if(ll<(t[k].l+t[k].r)/2)ans+=find(t[k].lc,ll,rr);
if(rr>(t[k].l+t[k].r)/2)ans+=find(t[k].rc,ll,rr);
t[k].sum=t[t[k].lc].sum+t[t[k].rc].sum;
return ans;
}
int main()
{
n=init();
for(int i=1;i<=n;i++)
a[i]=init();
Build(1,n+1);
m=init();
for(LL i=1;i<=m;i++)
{
x=init();
y=init();
z=init();
if(y>z)swap(y,z);
if(x==0)update(1,1,n+1);
if(x==1)printf("%lld\n",find(1,y,z+1));
}
}