标签:cut div wan leshi targe marked ssi i++ effect
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4027
解题思路:线段树区间更新,查询。主要问题在于如何解决快速对一个区间所有数据开根号然后求和 ----- 实际上是根本不用关心这个问题。2^64 在开根号7次之后已经变成1了,继续开根号没意义。
因此,对于每次更新,如果这个区间长度和值一样(全部为1)直接返回,否则更新到点然后更新父节点。
查询就和普通区间查询一样即可。
需要注意X Y的大小关系,加个if(x > y) swap(x, y)即可
代码:
1 const int maxn = 1e5 + 5; 2 ll A[maxn], tree[maxn * 4]; 3 int n, m; 4 5 void build(int l, int r, int k){ 6 if(l == r){ 7 tree[k] = A[l]; 8 return; 9 } 10 int mid = (l + r) / 2; 11 build(l, mid, k << 1); 12 build(mid + 1, r, k << 1 | 1); 13 tree[k] = tree[k << 1] + tree[k << 1 | 1]; 14 } 15 void update(int ul, int ur, int l, int r, int k){ 16 if(tree[k] == (r - l + 1)) return; 17 if(ul > r || ur < l) return; 18 if(l == r && tree[k] != 1) { 19 tree[k] = floor(sqrt(tree[k])); 20 return; 21 } 22 23 int mid = (l + r) >> 1, lc = k << 1, rc = k << 1 | 1; 24 update(ul, ur, l, mid, lc); 25 update(ul, ur, mid + 1, r, rc); 26 tree[k] = tree[lc] + tree[rc]; 27 } 28 ll query(int ql, int qr, int l, int r, int k){ 29 if(ql <= l && qr >= r) return tree[k]; 30 if(ql > r || qr < l) return 0; 31 32 int mid = (l + r) >> 1, lc = k << 1, rc = k << 1 | 1; 33 ll ans1 = query(ql, qr, l, mid, lc); 34 ll ans2 = query(ql, qr, mid + 1, r, rc); 35 return ans1 + ans2; 36 } 37 38 int main(){ 39 int t = 1; 40 while(scanf("%d", &n) != EOF){ 41 printf("Case #%d:\n", t++); 42 for(int i = 1; i <= n; i++) 43 scanf("%lld", &A[i]); 44 build(1, n, 1); 45 int m; 46 scanf("%d", &m); 47 while(m--){ 48 int a, b, c; 49 scanf("%d %d %d", &a, &b, &c); 50 if(b > c) swap(b, c); 51 if(a == 0){ 52 update(b, c, 1, n, 1); 53 } 54 else{ 55 printf("%lld\n", query(b, c, 1, n, 1)); 56 } 57 } 58 puts(""); 59 } 60 }
题目:
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65768/65768 K (Java/Others)
Total Submission(s): 17803 Accepted Submission(s): 4176
HDU 4027 Can you answer these queries?
标签:cut div wan leshi targe marked ssi i++ effect
原文地址:http://www.cnblogs.com/bolderic/p/7295224.html