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
",query(1,1,n,l,r));
		}
	}
	return 0;
}
原文地址:https://www.cnblogs.com/New-ljx/p/15338169.html