http://acm.hdu.edu.cn/showproblem.php?pid=4027
【更新区间,查询区间】的线段树,必须抓住修改6次以后每个数必然会变成1,然后以后的修改都将不起作用,在此之前的更新都是暴力更新。这是相当简单的题!
我的做法是记录那些区间里的数都是小于2的,然后在更新的时候就不必更新那那些区间了。不过这题在数据格式中有个小trick,就是给出的区间范围的两个指针x可以大于y,这时在区间修改之前要交换回来。我就是在这个惯性思维的小trick上卡了一个下午。。。。。囧!
View Code
1 #include <cstdio> 2 #include <cstdlib> 3 #include <cmath> 4 #include <cassert> 5 #include <algorithm> 6 7 #define lson l, m, rt << 1 8 #define rson m + 1, r, rt << 1 | 1 9 10 using namespace std; 11 const int maxn = 100001; 12 typedef __int64 ll; 13 14 bool st[maxn << 2]; 15 ll sum[maxn << 2]; 16 17 void up(int rt){ 18 sum[rt] = sum[rt << 1] + sum[rt << 1 | 1]; 19 st[rt] = st[rt << 1] && st[rt << 1 | 1]; 20 } 21 22 void build(int l, int r, int rt){ 23 if (l == r){ 24 scanf("%I64d", &sum[rt]); 25 assert(sum[rt] >= 0); 26 st[rt] = (sum[rt] < 2); 27 28 return ; 29 } 30 int m = (l + r) >> 1; 31 32 build(lson); 33 build(rson); 34 up(rt); 35 } 36 37 void update(int L, int R, int l, int r, int rt){ 38 if (L <= l && r <= R && st[rt]){ 39 return ; 40 } 41 if (l == r){ 42 sum[rt] = (ll) sqrt((double)sum[rt]); 43 st[rt] = (sum[rt] < 2); 44 45 return ; 46 } 47 int m = (l + r) >> 1; 48 49 if (L <= m) update(L, R, lson); 50 if (m < R) update(L, R, rson); 51 up(rt); 52 } 53 54 ll query(int L, int R, int l, int r, int rt){ 55 if (L <= l && r <= R){ 56 return sum[rt]; 57 } 58 ll ret = 0; 59 60 int m = (l + r) >> 1; 61 62 if (L <= m){ 63 ret += query(L, R, lson); 64 } 65 if (m < R){ 66 ret += query(L, R, rson); 67 } 68 69 return ret; 70 } 71 72 int main(){ 73 int n, m, cc = 0; 74 #ifndef ONLINE_JUDGE 75 freopen("in", "r", stdin); 76 #endif 77 while (~scanf("%d", &n)){ 78 build(1, n, 1); 79 cc++; 80 81 scanf("%d", &m); 82 printf("Case #%d:\n", cc); 83 while (m--){ 84 int op, l, r; 85 86 scanf("%d%d%d", &op, &l, &r); 87 if (op){ 88 if (r < l) swap(l, r); 89 assert(l <= r); 90 printf("%I64d\n", query(l, r, 1, n, 1)); 91 } 92 else{ 93 if (r < l) swap(l, r); 94 assert(l <= r); 95 update(l, r, 1, n, 1); 96 } 97 } 98 puts(""); 99 } 100 101 return 0; 102 }
——written by Lyon