Q - Can you answer these queries? (线段树&区间开平方修改)
思路:线段树模板改编,需要对update进行剪枝,因为一个数最多开平方到1就为止了,判断一下这个区间和是否等于该区间长度即可。还有需要注意一点得是x,y未知,若x>y,需要swap一下。。。。
AC代码:
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N=1e5+5;
struct node{
int l,r;
ll s;
}a[N];
void re(int x){
a[x].s=a[x<<1].s+a[x<<1|1].s;
}
void build(int x,int l,int r){
a[x].l=l,a[x].r=r;
if(l==r){
scanf("%lld",&a[x].s);
return;
}
int mid=(l+r)>>1;
build(x<<1,l,mid);
build(x<<1|1,mid+1,r);
re(x);
}
void update(int x,int l,int r){
if(a[x].l==a[x].r){
a[x].s=(ll)sqrt(1.0*a[x].s);
return;
}
if(a[x].l>=l&&a[x].r<=r&&a[x].r-a[x].l+1==a[x].s) return;///剪纸.因为最多开平方到1.
int mid=(a[x].l+a[x].r)>>1;
if(l<=mid) update(x<<1,l,r);
if(r>mid) update(x<<1|1,l,r);
re(x);
}
ll query(int x,int l,int r){
if(a[x].l>=l&&a[x].r<=r) return a[x].s;
else if(a[x].r<l||a[x].l>r) return 0;
int mid=(a[x].l+a[x].r)>>1;
return query(x<<1,l,r)+query(x<<1|1,l,r);
}
int main(){
int n,m,k=0;
while(~scanf("%d",&n)){
memset(a,0,sizeof a);///多组记得初始化
build(1,1,n);
scanf("%d",&m);
printf("Case #%d:\n",++k);
while(m--){
int op,x,y;
scanf("%d%d%d",&op,&x,&y);
if(x>y) swap(x,y);//可能存在x>y得情况。。
if(!op) update(1,x,y);
else printf("%lld\n",query(1,x,y));
}
puts("");
}
return 0;
}