又是线段树。
区间开平方求和,套路题。
如果开到了1就不用再开下去了,否则直接到底。
记得 l > r 时交换 l r
1 #include <cstdio> 2 #include <cmath> 3 #include <algorithm> 4 typedef long long LL; 5 const int N = 100010; 6 struct SegmentTree { 7 LL sum[N << 2]; 8 bool vis[N << 2]; 9 10 inline void pushup(int l, int r, int o) { 11 if(l == r) { 12 if(sum[o] == 1) { 13 vis[o] = 1; 14 } 15 return; 16 } 17 sum[o] = sum[o << 1] + sum[o << 1 | 1]; 18 vis[o] = (sum[o] == (r - l + 1)); 19 return; 20 } 21 void change(int L, int R, int l ,int r, int o) { 22 if(vis[o]) { 23 return; 24 } 25 int mid = (l + r) >> 1; 26 if(l == r) { 27 sum[o] = (LL)(sqrt((long double)(sum[o]))); 28 pushup(l, r, o); 29 return; 30 } 31 if(L <= mid) { 32 change(L, R, l, mid, o << 1); 33 } 34 if(mid < R) { 35 change(L, R, mid + 1, r, o << 1 | 1); 36 } 37 pushup(l, r, o); 38 return; 39 } 40 LL ask(int L, int R, int l, int r, int o) { 41 if(L <= l && r <= R) { 42 return sum[o]; 43 } 44 if(r < L || R < l) { 45 return 0; 46 } 47 int mid = (l + r) >> 1; 48 return ask(L, R, l, mid, o << 1) + ask(L, R, mid + 1, r, o << 1 | 1); 49 } 50 void build(int l, int r, int o) { 51 if(l == r) { 52 scanf("%lld", &sum[o]); 53 pushup(l, r, o); 54 return; 55 } 56 int mid = (l + r) >> 1; 57 build(l, mid, o << 1); 58 build(mid + 1, r, o << 1 | 1); 59 pushup(l, r, o); 60 return; 61 } 62 }SgT; 63 64 int main() { 65 int n; 66 scanf("%d", &n); 67 SgT.build(1, n, 1); 68 int m; 69 scanf("%d", &m); 70 int f, x, y; 71 while(m--) { 72 scanf("%d%d%d", &f, &x, &y); 73 if(x > y) { 74 std::swap(x, y); 75 } 76 if(f) { 77 printf("%lld ",SgT.ask(x, y, 1, n, 1)); 78 } 79 else { 80 SgT.change(x, y, 1, n, 1); 81 } 82 } 83 return 0; 84 }