给定长度为数组,执行两种操作:
  1. 区间根号:将 这个区间中的全部元素修改为其开根号后的值,即
  2. 区间和查询:输出下标在这个区间中的所有元素之和,即
维护区间开根号十分困难,但是仔细想会知道开根号的次数不会超过5次(连续开根号次就变成1了,即使是级别,连续开根号次就变成1了)
所以需要维护区间的最大值,如果这个区间的最大值是1,那么这个区间就不需要再执行操作1了,直接跳过。如果不为1,就直接暴力循环区间将每一个数开根号。最多只会修改次,其中是一个很小的常数。
总代码:
#include<bits/stdc++.h>
using namespace std;

#define endl '\n'
#define int long long
#define IOS ios::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL);
#define HelloWorld IOS;


const int N = 1e5 + 10;


struct Node{
    int l, r;
    int sum, Max;
}tr[4 * N];

int n, m, a[N];


void push_up(int u){
    tr[u].sum = tr[u << 1].sum + tr[u << 1 | 1].sum;
    tr[u].Max = max(tr[u << 1].Max, tr[u << 1 | 1].Max);
}

void build(int u, int l, int r){
    if(l == r) tr[u] = {l, r, a[l], a[l]};
    else{
        tr[u] = {l, r, 0, 0};
        int mid = (l + r) >> 1;
        build(u << 1, l, mid);
        build(u << 1 | 1, mid + 1, r);
        push_up(u);
    }
}

void modify_sqrt(int u, int pos){
    if(tr[u].l == pos && pos == tr[u].r){
        tr[u].sum = sqrt(tr[u].sum);
        tr[u].Max = sqrt(tr[u].Max);
        return ;
    }
    else{
        int mid = (tr[u].l + tr[u].r) >> 1;
        if(pos <= mid) modify_sqrt(u << 1, pos);
        else modify_sqrt(u << 1 | 1, pos);
        push_up(u);
    }
}

void modify(int u, int l, int r){
    if(l <= tr[u].l && tr[u].r <= r){
        if(tr[u].Max != 1){
            for(int i = tr[u].l; i <= tr[u].r; i ++){
                modify_sqrt(1, i);
            }
        }
        return ;
    }
    else{
        int mid = (tr[u].l + tr[u].r) >> 1;
        if(l <= mid) modify(u << 1, l, r);
        if(r > mid) modify(u << 1 | 1, l, r);
        push_up(u);
    }
}

int query(int u, int l, int r){
    if(l <= tr[u].l && tr[u].r <= r) return tr[u].sum;
    else{
        int sum = 0;
        int mid = (tr[u].l + tr[u].r) >> 1;
        if(l <= mid) sum += query(u << 1, l, r);
        if(r > mid) sum += query(u << 1 | 1, l, r);
        return sum;
    }
}

signed main(){
    HelloWorld;
    
    cin >> n >> m;
    for(int i = 1; i <= n; i ++) cin >> a[i];
    build(1, 1, n);
    
    while(m --){
        int op; cin >> op;
        if(op == 1){
            int l, r; cin >> l >> r;
            modify(1, l, r);
        }
        if(op == 2){
            int l, r; cin >> l >> r;
            cout << query(1, l, r) << endl;
        }
    }
    return 0;
}