区间每个点的值都开方。
由于数据范围,开方的次数较小。一个点开方的次数不超过7次,所以可以做到每个点都修改,同时注意限制修改次数。
#include <bits/stdc++.h>//线段树区间不等更新
using namespace std;
const int N=1e5+5;
typedef long long ll;
ll a[N],tree[N<<2];
void build(int l,int r,int rt)
{
if(l==r)
{
tree[rt]=a[l];
return;
}
int mid=(l+r)>>1;
build(l,mid,rt<<1);
build(mid+1,r,rt<<1|1);
tree[rt]=tree[rt<<1]+tree[rt<<1|1];
}
void update(int L,int R,int l,int r,int rt)
{
if(tree[rt]==r-l+1)//不能少,限定修改次数,开方次数有限,所以可以做到单点修改
return;
if(l==r)
{
tree[rt]=(ll)sqrt(1.0*tree[rt]);
return;
}
int mid=(l+r)>>1;
if(L<=mid)
update(L,R,l,mid,rt<<1);
if(R>mid)
update(L,R,mid+1,r,rt<<1|1);
tree[rt]=tree[rt<<1]+tree[rt<<1|1];
}
ll query(int L,int R,int l,int r,int rt)
{
if(L<=l&&r<=R)
return tree[rt];
ll ans=0;
int mid=(l+r)>>1;
if(L<=mid)
ans+=query(L,R,l,mid,rt<<1);
if(R>mid)
ans+=query(L,R,mid+1,r,rt<<1|1);
return ans;
}
int main()
{
int n,m,cnt=0;
while(scanf("%d",&n)!=EOF)
{
for(int i=1;i<=n;i++)
scanf("%lld",&a[i]);
build(1,n,1);
scanf("%d",&m);
int t,x,y;
printf("Case #%d:\n",++cnt);
for(int i=1;i<=m;i++)
{
scanf("%d%d%d",&t,&x,&y);
if(x>y)//坑
swap(x,y);
if(t==0)
update(x,y,1,n,1);
else
printf("%lld\n",query(x,y,1,n,1));
}
puts("");
}
return 0;
}