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;
}