P4145 上帝造题的七分钟 2 / 花神游历各国

题目

P4145 上帝造题的七分钟 2 / 花神游历各国_第1张图片

思路

是一个比较简单的线段树题,线段树的原理就是分段存数据,然后通过递归实现区间操作
首先,直接进行单点修改肯定会超时
所以我们加个剪枝 优化
如果是0/1的话,再开根就没有意义了,所以如果是0或者1就return

代码

#include
using namespace std;
#define int long long
#define lc(x) x<<1
#define rc(x) x<<1|1
const int maxn=1e5+5;
int n,m;
int v[maxn<<2];
int s[maxn<<2],ax[maxn<<2];
void pushup(int x){//往上更新数据
	s[x]=s[lc(x)]+s[rc(x)];
	ax[x]=max(ax[lc(x)],ax[rc(x)]);
}
void build(int x,int l,int r){//建树
	if(l==r) { s[x]=ax[x]=v[l];return; }
	int mid=l+r>>1;
	build(lc(x),l,mid),build(rc(x),mid+1,r);
	pushup(x);
}
void modify(int x,int l,int r,int L,int R){//修改操作
	if(l==r) { s[x]=sqrt(s[x]),ax[x]=sqrt(ax[x]);return; }//开根操作
	if(ax[x]<=1) return;//优化
	int mid=l+r>>1;
	if(L<=mid) modify(lc(x),l,mid,L,R);//递归
	if(R>mid) modify(rc(x),mid+1,r,L,R);
	pushup(x); 
}
int query(int x,int l,int r,int L,int R){//查询操作
	if(L<=l&&r<=R) return s[x];
	int mid=l+r>>1;
	int res=0;
	if(L<=mid) res+=query(lc(x),l,mid,L,R);
	if(R>mid) res+=query(rc(x),mid+1,r,L,R);
	return res;
}
signed main()
{
	cin>>n;
	for(int i=1;i<=n;i++) cin>>v[i];
	build(1,1,n);
	cin>>m;
	while(m--){
		int if_case;cin>>if_case;
		int l,r;cin>>l>>r;
		if(l>r) swap(l,r);
		switch (if_case){
			case 1:cout<<query(1,1,n,l,r)<<endl;break;
			case 0:modify(1,1,n,l,r);break;
		}
	}
	return 0;
}

你可能感兴趣的:(算法,数据结构,c++,线段树)