题目链接 :点击打开链接
题目要求开根那么再大的一个数不超过十次开根就会变成1,那么此时就不需要再更新了,所以用线段树只需特判这个点就可以了。
题解:
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
using namespace std;
typedef long long ll;
const int mx=100010;
int n,m;
ll sum[mx<<2];
void push_up(int rt){
sum[rt]=sum[rt<<1]+sum[rt<<1|1];
}
void build(int l,int r,int rt){
if(l==r){
scanf("%lld",sum+rt);
return ;
}
int m=(l+r)>>1;
build(lson);
build(rson);
push_up(rt);
}
void update(int l,int r,int rt,int L,int R){
if(sum[rt]==r-l+1) return ;
if(l==r){
sum[rt]=sqrt(sum[rt]);
return ;
}
int m=(l+r)>>1;
if(L<=m) update(lson,L,R);
if(R>m) update(rson,L,R);
push_up(rt);
}
ll query(int l,int r,int rt,int L,int R){
if(l>=L&&R>=r) return sum[rt];
int m=(l+r)>>1;
ll ans=0;
if(L<=m) ans+=query(lson,L,R);
if(R>m) ans+=query(rson,L,R);
return ans;
}
int main(){
int cases=1;
while(cin>>n){
build(1,n,1);
int q,x,y,t;
scanf("%d",&q);
printf("Case #%d:\n",cases++);
while(q--){
scanf("%d%d%d",&t,&x,&y);
if(x>y) swap(x,y);
if(t){
printf("%lld\n",query(1,n,1,x,y));
}else{
update(1,n,1,x,y);
}
}
puts("");
}
return 0;
}