HDU_4027_线段树区间开方
- 剪枝:开方等于7次,值等1
- 以为每个点的值不一样,所以开方是要每个点开方,不能延迟标记
long long
存sum
- 看别人博客:
x
居然可以>y
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61#include <iostream>
#include <string.h>
#include <cmath>
using namespace std;
const int maxn = 1e5+5;
struct segementTree {
int left, right;
long long sum;
#define left(x) tree[x].left
#define right(x) tree[x].right
#define sum(x) tree[x].sum
} tree[4*maxn];
int n,m;
void build(int p,int left,int right) {
left(p) = left; right(p) = right;
if (left == right) {
cin >> sum(p); return;
}
int mid = (left + right) / 2;
build(2*p,left,mid);
build(2*p+1,mid+1,right);
sum(p) = sum(2*p) + sum(2*p+1);
}
void update(int p, int left, int right) { //由于每个点的值不一样,所有开方要更新每一个点,不能打延迟标记
// 当更新7次以上,值就为1,那么剪枝,即使add()>=1也不用管该节点的子树
if (sum(p) == right(p) - left(p) + 1) return;
if (left(p) == right(p)) {
sum(p) = sqrt(1.0 * sum(p));
return;
}
int mid = (left(p) + right(p)) / 2;
if (left <= mid) update(2*p,left,right);
if (mid < right) update(2*p+1,left,right);
sum(p) = sum(2*p) + sum(2*p+1);
}
long long query(int p,int left,int right) {
if (left <= left(p) && right(p) <= right) return sum(p);
int mid = (left(p) + right(p)) / 2;
long long res = 0;
if (left <= mid) res+=query(2*p,left,right);
if (mid < right) res+=query(2*p+1,left,right);
return res;
}
int main() {
// freopen("a.txt","r",stdin);
int cnt = 0;
while (scanf("%d",&n) != EOF) {
build(1,1,n);
scanf("%d",&m);
printf("Case #%d:\n",++cnt);
int t, x, y;
for (int i = 1; i <= m; i++) {
scanf("%d%d%d",&t,&x,&y);
if (x > y) { int temp = x; x = y; y = temp; }
if (t) printf("%lld\n",query(1,x,y));
else update(1,x,y);
}
printf("\n");
}
return 0;
}
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!