//#include #include #include #include #include #include #include #include #include #include using namespace std; typedef long long LL; const int N = 1e6 + 5; LL a[N]; struct Node { int l, r; LL sum; //区间和 } tr[N << 2]; void pushup(int u) { tr[u].sum = tr[u << 1].sum + tr[u << 1 | 1].sum; } void build(int u, int l, int r) { tr[u] = {l, r}; if (l == r) { tr[u].sum = a[l]; //构建线段树,叶子节点给定初始值 return; } int mid = (l + r) >> 1; build(u << 1, l, mid), build(u << 1 | 1, mid + 1, r); //更新父节点信息 pushup(u); } void modify(int u, int l, int r) { //减枝 如果区间和等于区间长度,说明每个节点值都是1,此时再开方没有意义 if (tr[u].sum == (tr[u].r - tr[u].l + 1)) return; //如果在区间内 if (tr[u].l == tr[u].r) { tr[u].sum = (LL)sqrt(tr[u].sum); //暴力开方 return; } //中点 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); //向父节点传递统计信息 pushup(u); } //非常标准的查询 LL query(int u, int l, int r) { if (r < tr[u].l || l > tr[u].r) return 0; if (l <= tr[u].l && tr[u].r <= r) return tr[u].sum; return query(u << 1, l, r) + query(u << 1 | 1, l, r); } int main() { int n, q, cas = 1; scanf("%d", &n); for (int i = 1; i <= n; i++) scanf("%lld", &a[i]); build(1, 1, n); scanf("%d", &q); while (q--) { int c, l, r; scanf("%d%d%d", &c, &l, &r); if (l > r) swap(l, r); /// l可能大于r if (c == 0) modify(1, l, r); else printf("%lld\n", query(1, l, r)); } printf("\n"); return 0; }