原题传送:http://acm.hdu.edu.cn/showproblem.php?pid=4027
线段树。
一个很大的数(< 263),最多也就进行几次开平方操作就会达到1了,所以每次更新,如果区间有的点不为1,那么就直接更新它,如果,区间的值都是1了,那么必须直接返回。
1 #include <stdio.h> 2 #include <string.h> 3 #include <math.h> 4 #include <stdlib.h> 5 #define lson (cur << 1) 6 #define rson (cur << 1 | 1) 7 #define N 100005 8 #define LL __int64 9 10 int n, m; 11 LL a[N]; 12 LL tree[N << 2]; // 记录区间最大值,如果最大值为1,说明该区间值全为1 13 LL sum[N << 2]; 14 15 inline LL max(LL x, LL y){return x > y ? x : y;} 16 inline void swap(int &x, int &y){int tmp = x; x = y; y = tmp;} 17 18 void pushup(int cur) 19 { 20 tree[cur] = max(tree[lson], tree[rson]); 21 sum[cur] = sum[lson] + sum[rson]; 22 } 23 24 void update(int cur, int l, int r, int s, int t) 25 { 26 if(tree[cur] == 1) 27 return ; 28 if(l == r) 29 { 30 tree[cur] = (LL)sqrt((double)tree[cur]); 31 sum[cur] = tree[cur]; 32 return ; 33 } 34 int mid = (l + r) >> 1; 35 if(mid >= s) 36 update(lson, l, mid, s, t); 37 if(mid < t) 38 update(rson, mid + 1, r, s, t); 39 pushup(cur); 40 } 41 42 void query(int cur, int l, int r, int s, int t, LL &ans) 43 { 44 if(l >= s && r <= t) 45 { 46 ans += sum[cur]; 47 return ; 48 } 49 int mid = (l + r) >> 1; 50 if(mid >= s) 51 query(lson, l, mid, s, t, ans); 52 if(mid + 1 <= t) 53 query(rson, mid + 1, r, s, t, ans); 54 } 55 56 void build(int cur, int l, int r) 57 { 58 if(l == r) 59 { 60 sum[cur] = tree[cur] = a[l]; 61 return ; 62 } 63 int mid = (l + r) >> 1; 64 build(lson, l, mid); 65 build(rson, mid + 1, r); 66 pushup(cur); 67 } 68 69 int main() 70 { 71 int i, op, x, y, cas = 1; 72 LL ans; 73 while(scanf("%d", &n) != EOF) 74 { 75 for(i = 1; i <= n; i ++) 76 scanf("%I64d", &a[i]); 77 build(1, 1, n); 78 scanf("%d", &m); 79 printf("Case #%d:\n", cas ++); 80 while(m --) 81 { 82 scanf("%d%d%d", &op, &x, &y); 83 if(x > y) swap(x, y); // ! 84 if(op == 0) 85 { 86 update(1, 1, n, x, y); 87 } 88 else if(op == 1) 89 { 90 ans = 0; 91 query(1, 1, n, x, y, ans); 92 printf("%I64d\n", ans); 93 } 94 } 95 putchar('\n'); 96 } 97 return 0; 98 }