# 9.21 考试

T原

区间开方+区间求和;考场上打了个线段树,维护最大值和和,时间复杂度玄学;
不知道为神魔过不去

#include<iostream>
#include<cstdio>
#include<cmath>
#define int long long 
#define l(o) (o<<1)
#define r(o) (o<<1|1)
#define mid ((l+r)>>1)
using namespace std;
const int N=5e5+7;

int n,m;
int sum[N<<2];
int maxn[N<<2];

void up(int o){
	sum[o]=sum[l(o)]+sum[r(o)];
	maxn[o]=max(maxn[l(o)],maxn[r(o)]);
}

void build(int o,int l,int r){
	if(l==r){
		scanf("%d",&maxn[o]);
		sum[o]=maxn[o];
		return;
	}
	build(l(o),l,mid);
	build(r(o),mid+1,r);
	up(o);
}

void change(int o,int l,int r,int L,int R){
	if(maxn[o]<=1) return;
	if(l==r){
		sum[o]=maxn[o]=sqrt(sum[o]);
		return;
	}
	if(L<=mid) change(l(o),l,mid,L,R);
	if(R>mid) change(r(o),mid+1,r,L,R);
	up(o);
}

int ask(int o,int l,int r,int L,int R){
	if(L<=l&&R>=r){
		return sum[o];
	}
	int res=0;
	if(L<=mid) res=ask(l(o),l,mid,L,R);
	if(R>mid) res+=ask(r(o),mid+1,r,L,R);
	return res;
}

main(){
//	freopen("sqrt.in","r",stdin);
//	freopen("sqrt.out","w",stdout);
	scanf("%lld",&n);
	build(1,1,n);
	scanf("%lld",&m);
	for(int i=1;i<=m;i++){
		int opt,x,y;
		scanf("%lld%lld%lld",&opt,&x,&y);
		if(x>y) swap(x,y);
		if(opt==1){
			cout<<1LL*ask(1,1,n,x,y)<<"\n";
		
		}
		if(opt==0){
			change(1,1,n,x,y);
		}
	}
	fclose(stdin);
	fclose(stdout);
	return 0;
}
/*
5 5
0 9 3 5 9
1 2 2
0 1 4
0 4 5
0 3 4
1 1 3
*/
上一篇:2020.10.07【NOIP提高A组】模拟 JZOJ


下一篇:增减序列