线段树,可是时间复杂度可能会爆掉,需要优化:
看代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#define ll long long
#define MAXN 100005
using namespace std;
int n,m;
ll s[4*MAXN];
bool mark[4*MAXN];
void up(int p){
s[p]=s[p*2]+s[p*2+1];
mark[p]=mark[p*2]&&mark[p*2+1];
return ;
}
void build(int p,int l,int r){
if(l==r){
scanf("%lld",&s[p]);
if(s[p]==1||s[p]==0)
mark[p]=true;
return ;
}
int m=l+r>>1;
build(p*2,l,m);
build(p*2+1,m+1,r);
up(p);
return ;
}
void update(int p,int l,int r,int x,int y){
if(mark[p]) return ;
if(r<x||l>y) return ;
if(l==r){
s[p]=sqrt(s[p]);
if(s[p]==1||s[p]==0)
mark[p]=true;
return ;
}
int m=l+r>>1;
update(p*2,l,m,x,y);
update(p*2+1,m+1,r,x,y);
up(p);
}
ll query_sum(int p,int l,int r,int x,int y){
if(r<x||l>y) return 0LL;
if(x<=l&&r<=y){
return s[p];
}
int m=l+r>>1;
ll ret=0;
ret+=query_sum(p*2,l,m,x,y);
ret+=query_sum(p*2+1,m+1,r,x,y);
return ret;
}
int main(){
scanf("%d",&n);
build(1,1,n);
scanf("%d",&m);
for(int i=1,t,l,r;i<=m;i++){
cin>>t>>l>>r;
if(t==1){
cout<<query_sum(1,1,n,l,r)<<"\n";
}else{
update(1,1,n,l,r);
}
}
return 0;
}