P4145 上帝造题的七分钟 2 / 花神游历各国(线段树)
区间求和+区间开平方。
对于区间开平方,暴力进行单点开平方,存一个max,如果max<=1,那么不需要开平方。
#include<cstdio>
#include<iostream>
#include<cmath>
using namespace std;
typedef long long ll;
const int N=100005;
int n,m;
ll a[N];
ll read(){
ll num=0,f=1;
char c=getchar();
while(c<'0'||c>'9'){
if(c=='-') f=-1;
c=getchar();
}
while(c>='0'&&c<='9'){
num=num*10+c-'0';
c=getchar();
}
return num*f;
}
struct node{
ll max;
ll sum;
}t[N<<2];
void pushup(int k){
t[k].max=max(t[k<<1].max,t[k<<1|1].max);
t[k].sum=t[k<<1].sum+t[k<<1|1].sum;
}
void build(int k,int l,int r){
if(l==r){
t[k].max=t[k].sum=a[l];
return;
}
int mid=(l+r)>>1;
build(k<<1,l,mid);
build(k<<1|1,mid+1,r);
pushup(k);
}
ll query(int k,int l,int r,int x,int y){
if(x<=l&&r<=y){
return t[k].sum;
}
int mid=(l+r)>>1;
ll res=0;
if(x<=mid) res+=query(k<<1,l,mid,x,y);
if(y>mid) res+=query(k<<1|1,mid+1,r,x,y);
return res;
}
void update(int k,int l,int r,int x,int y){
if(t[k].max<=1) return;
if(l==r){
t[k].sum=sqrt(t[k].sum);
t[k].max=sqrt(t[k].max);
return;
}
int mid=(l+r)>>1;
if(x<=mid&&t[k<<1].max>1) update(k<<1,l,mid,x,y);
if(y>mid&&t[k<<1|1].max>1) update(k<<1|1,mid+1,r,x,y);
pushup(k);
}
int main(){
n=read();
for(int i=1;i<=n;i++) a[i]=read();
build(1,1,n);
m=read();
for(int i=1;i<=m;i++){
int k=read(),l=read(),r=read();
if(l>r) swap(l,r);
if(k==0){
update(1,1,n,l,r);
}
if(k==1){
printf("%lld\n",query(1,1,n,l,r));
}
}
return 0;
}