Can you answer these queries?
题目
给定N个元素,操作M次区间修改和区间查询,区间修改是把区间内所有元素各自进行开方,区间查询是查询这个区间的和。初始元素小于
分析
对于此题,开方的操作是很难上下传递的,而我们知道开方速度是很快的,我测了一下1e18开方只需要6次,所以我们完全可以使用暴力来修改,假如全都修改到了1,也就6*1e5的样子。对于区间和已经等于区间长度的,就不再往下递归进行修改了,因为没必要。
坑点
输入的区间不一定是前者小于后者
每一组输出要多输出一个空行
AC代码
#include <iostream>
#include <algorithm>
#include <cmath>
using namespace std;
typedef long long ll;
const ll maxn = 1e5+10;
ll N,M;
struct node{
ll l,r,sum;
}tr[4*maxn];
ll arr[maxn];
void pushup(ll u){
node &fa = tr[u],&L = tr[u*2],&R = tr[u*2+1];
fa.sum = L.sum + R.sum;
}
void build(ll u,ll l,ll r){
if(l == r) tr[u] = {l,r,arr[l]};
else{
tr[u] = {l,r};
ll mid = l+r>>1;
build(u*2,l,mid);
build(u*2+1,mid+1,r);
pushup(u);
}
}
void modify(ll u,ll l,ll r){
if(tr[u].l>=l && tr[u].r<=r){
if(tr[u].r-tr[u].l+1 == tr[u].sum) return ;//不用再递归了
if(tr[u].r == tr[u].l) {
tr[u].sum = arr[tr[u].l] = sqrt(arr[tr[u].l]);
}else{
modify(u*2,l,r);
modify(u*2+1,l,r);
pushup(u);
}
}else{
int mid = (tr[u].l+tr[u].r)>>1;
if(l<=mid) modify(u*2,l,r);
if(r>mid) modify(u*2+1,l,r);
pushup(u);
}
}
ll query(ll u,ll l,ll r){
if(tr[u].l>=l && tr[u].r<=r){
return tr[u].sum;
}else{
int mid = (tr[u].l+tr[u].r)>>1;
ll sum = 0;
if(l<=mid) sum += query(u*2,l,r);
if(r>mid) sum += query(u*2+1,l,r);
return sum;
}
}
int main(){
int kase = 0;
while(scanf("%lld",&N) != EOF){
printf("Case #%d:\n",++kase);
for(int i = 1;i<=N;i++) scanf("%lld",&arr[i]);
build(1,1,N);
cin>>M;
ll t,a,b;
while(M--){
scanf("%lld %lld %lld",&t,&a,&b);
if(a>b) swap(a,b);
if(t == 0){
modify(1,a,b);
}else{
printf("%lld\n",query(1,a,b));
}
}
puts("");
}
return 0;
} 
京公网安备 11010502036488号