「题意」: nnn 个数,每个数在 101810^{18}1018 范围内。
现在有「两种」操作
0 x y把区间 [x,y] 内的每个数开方
1 x y询问区间 [x,y] 的每个数的和
啊其实就是注意到
即使是10^18开根号7次也变成1了
变成1以后再怎么开还是1,所以就可以不管了
就是这里的一个优化就可以过了
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define ls cur<<1
#define rs cur<<1|1
#define LL long long
#define maxn 100005
using namespace std;
int n,m,num;
LL a[maxn];
inline LL rd(){//我天快读没开longlong竟然tle
LL x=0,f=1; char c=' ';
while(c<'0' || c>'9') {if(c=='-')f=-1;c=getchar();}
while(c<='9' && c>='0') x=x*10+c-'0',c=getchar();
return x*f;
}
struct Tree{
int l,r;
LL sum;
}node[maxn*4];
void pushup(int cur){
node[cur].l=node[ls].l; node[cur].r=node[rs].r;
node[cur].sum=node[ls].sum+node[rs].sum;
}
void build(int cur,int L,int R){
if(L==R) {
node[cur].l=node[cur].r=L,node[cur].sum=a[L];
return;
}
int mid=(L+R)>>1;
build(ls,L,mid); build(rs,mid+1,R);
pushup(cur);
}
void updata(int cur,int L,int R){
if(node[cur].r-node[cur].l+1==node[cur].sum) return;//!!
if(node[cur].l==node[cur].r) {
node[cur].sum=sqrt(node[cur].sum); return;
}
int mid=(node[cur].l+node[cur].r)>>1;
if(L<=mid) updata(ls,L,R);
if(mid<R) updata(rs,L,R);
pushup(cur);
}
LL query(int cur,int L,int R){
if(L<=node[cur].l && node[cur].r<=R)
return node[cur].sum;
int mid=(node[cur].l+node[cur].r)>>1;
LL tot=0;
if(L<=mid) tot+=query(ls,L,R);
if(mid<R) tot+=query(rs,L,R);
return tot;
}
int main(){
while(~scanf("%d",&n)){
num++; printf("Case #%d:\n",num);
for(int i=1;i<=n;i++) a[i]=rd();
build(1,1,n);
m=rd();
for(int i=1;i<=m;i++){
int ty=rd(),x=rd(),y=rd();
if(x>y) swap(x,y);
if(ty==0) updata(1,x,y);
else printf("%lld\n",query(1,x,y));
}
printf("\n");
}
return 0;
}