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