HDU 4027

题目:

http://acm.hdu.edu.cn/showproblem.php?pid=4027

先说这个题的关键:

  1. 这道题不同于普通的成段更新,需要对每一个值进行求根操作,而如果每次都对区间的每个点进行求根操作的话,复杂度肯定很高。所以,第一个关键点就是,一个数不断开方后的结果,最后一定会变成1的,即便是2的64次方这么大的数,开方7次后也会变成1。所以,我们对一个点最多也就更新7次。
  2. 一个很坑的点就是,题目并没有告诉x>y,这个错误很隐秘,所以仔细读题很重要。。。

大部分代码都是正常的线段树操作,不同的是,lazy数组记录该节点维护的区间是否还需要更新,pushup函数中,有个&&操作,就是当两子节点的lazy值都为1,父节点也为1,说明这两个数都不需要操作了。

update中要注意只有当lazy值不为1的时候才需要更新下去,若为1则说明这段区间内的所有值已经都为1,不需要再进行开方运算了。

 1 #include<stdio.h>
 2 #include<math.h>
 3 #define maxn 100100
 4 #define lson l,m,rt*2
 5 #define rson m+1,r,rt*2+1
 6 long long tree[maxn<<2];
 7 int lazy[maxn<<2];
 8 void pushup(int rt){
 9     tree[rt] = tree[rt*2]+tree[rt*2+1];
10     lazy[rt] = lazy[rt*2]&&lazy[rt*2+1];
11 }
12 void build(int l,int r,int rt){
13     lazy[rt] = 0;
14     if(l==r){
15         scanf("%lld",&tree[rt]);
16         return;
17     }
18     int m = (l+r)/2;
19     build(lson);
20     build(rson);
21     pushup(rt);
22 }
23 void update(int a,int b,int l,int r,int rt){
24     if(l==r){
25         tree[rt] = sqrt(tree[rt]);
26         if(tree[rt]<=1){
27             lazy[rt] = 1;
28         }
29         return;
30     }
31     int m = (l+r)/2;
32     if(a<=m&&!lazy[rt])
33         update(a,b,lson);
34     if(b>m&&!lazy[rt])
35         update(a,b,rson);
36     pushup(rt);
37 }
38 long long query(int a,int b,int l,int r,int rt){
39     if(a<=l&&b>=r)
40         return tree[rt];
41     int m = (l+r)/2;
42     long long ret = 0;
43     if(a<=m)
44         ret += query(a,b,lson);
45     if(b>m)
46         ret += query(a,b,rson);
47     return ret;
48 }
49 int main(){
50     int n,cnt = 1;;
51     while(scanf("%d",&n)!=EOF){
52         build(1,n,1); 
53         int m;
54         scanf("%d",&m);
55         int flag = 1;
56         while(m--){
57             int t,x,y;
58             scanf("%d%d%d",&t,&x,&y);
59             if(x>y)
60                 x^=y^=x^=y;
61             if(t==0){
62                 update(x,y,1,n,1);
63             }else{
64                 if(flag == 1){
65                     printf("Case #%d:
",cnt);
66                     flag = 0;
67                 }
68                 printf("%lld
",query(x,y,1,n,1));
69             }
70         }
71         cnt++;
72         printf("
");
73     }
74     return 0;
75 }
原文地址:https://www.cnblogs.com/zqy123/p/5061337.html