一般的线段树模版题改了下, 不需要开lazy数组,而且执行到一定步数后可以剪枝,因为开方是个很快的步骤,后面就一直是1了,这题基本就需要改下update函数就行了
#include<cstring>
#include<iostream>
#include<cstdio>
#include<string>
#include<vector>
#include<queue>
#include<cmath>
using namespace std;
typedef long long ll;
const ll MAXN = 200000+10;
int n,m;
ll tree[MAXN<<2];
int cnt = 1;
void push_up(int rt){
tree[rt] = tree[rt<<1] + tree[rt<<1|1];
}
void build(int rt,int L,int R){
if(L == R){
scanf("%lld",&tree[rt]);
return;
}
int mid = (L+R)>>1;
build(rt<<1, L, mid);
build(rt<<1|1, mid+1, R);
push_up(rt);
}
void update(int L,int R,int l,int r,int rt)
{
if(tree[rt]==R-L+1)return;//没有这句就会超时
//剪枝 因为开方很快就是1了,很多无用的操作
if(L == R){
tree[rt]=(ll)(sqrt(tree[rt]));
return;
}
int mid = (L+R)>>1;
if(l<=mid)update(L,mid,l,r,rt<<1);
if(r>mid)update(mid+1,R,l,r,rt<<1|1);
push_up(rt);
}
ll query(int rt,int L,int R,int l,int r){
if(l>R || r<L) return 0;
if(l<=L && r>=R) return tree[rt];
// push_down(rt, L, R);
int mid = (L+R)>>1;
ll ans = query(rt<<1, L, mid, l, r) + query(rt<<1|1, mid+1, R, l, r);
return ans;
}
int main(){
// printf("123\n");
while (scanf("%d",&n) != EOF) {
build(1, 1, n);
scanf("%d",&m);
int a,b,c;
printf("Case #%d:\n",cnt++);
for(ll i=0;i<m;++i){
scanf("%d%d%d",&a,&b,&c);
if(b>c) swap(b, c);
if(a == 0){
update(1, n, b, c, 1);
}else{
ll ans = query(1, 1, n, b,c );
printf("%lld\n",ans);
}
}
printf("\n");
}
return 0;
}