HDU 4027 Can you answer these queries【线段树】

<题目链接>

题目大意:

给定一段序列,现在对指定区间进行两种操作:一是对指定区间进行修改,对其中的每个数字都开根号(开根号后的数字仍然取整);二是对指定区间进行查询,查询这段区间所有数字的和。

解题分析:

本题虽然是区间修改,但是不需要用 lazy标记,因为要对指定区间的每个数进行开根号的处理,也就是说,每次 update ,都要延伸到该区间涉及到的叶子节点,进行开根,而不是在叶子节点上端的某个节点就将开根的指令存储下来。那么是不是说我们每次只能对 update 的每个区间所涉及到的每个节点进行暴力的单点修改呢?很显然不是的,因为每个节点的值不超过2^63,所以每个值的有效开方次数并不多。所以我们对线段树的每个节点引入一个标记cnt,用它来记录该节点对应的区域是否全部不需要开方,如果不需要开方,那么就直接return ,终止无效更新,从而提高效率。

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <cmath>
 4 #include <algorithm>
 5 using namespace std;
 6 
 7 #define Lson rt<<1,l,mid
 8 #define Rson rt<<1|1,mid+1,r
 9 typedef long long ll;
10 const int M = 1e5+5;
11 int n;
12 ll tr[M<<2],arr[M];
13 bool fp[M<<2];
14 void Pushup(int rt){
15     if(fp[rt<<1]&&fp[rt<<1|1])fp[rt]=true;    //如果两个子区间全部不用开根号的话,那么该区间也标记为不用继续开根
16     else fp[rt]=false;
17     tr[rt]=tr[rt<<1]+tr[rt<<1|1];
18 }
19 void build(int rt,int l,int r){
20     if(l==r){
21         tr[rt]=arr[l];
22         return;
23     }
24     int mid=(l+r)>>1;
25     build(Lson);
26     build(Rson);
27     Pushup(rt);
28 }
29 void update(int rt,int l,int r,int L,int R){
30     if(fp[rt])return;      //如果遍历到不用继续向下更新的区间,则直接返回
31     if(l==r){
32         tr[rt]=sqrt(tr[rt]*1.0);
33         if(tr[rt]==1)fp[rt]=true;    //如果tr[rt]==1,那么该点就标记为不用继续开根
34         return;
35     }
36     int mid=(l+r)>>1;
37     if(L<=mid)update(Lson,L,R);
38     if(R>mid)update(Rson,L,R);
39     Pushup(rt);
40 }
41 ll query(int rt,int l,int r,int L,int R){
42     if(L<=l&&r<=R){
43         return tr[rt];
44     }
45     int mid=(l+r)>>1;
46     ll ans=0;
47     if(L<=mid)ans+=query(Lson,L,R);
48     if(R>mid)ans+=query(Rson,L,R);
49     return ans;
50 }
51 int main(){
52     int ncase=0;
53     while(scanf("%d",&n)!=EOF){
54         memset(fp,false,sizeof(fp));
55         for(int i=1;i<=n;i++)scanf("%lld",&arr[i]);
56         build(1,1,n);
57         int m;scanf("%d",&m);
58         printf("Case #%d:\n",++ncase);
59         while(m--){
60             int op,x,y;
61             scanf("%d%d%d",&op,&x,&y);
62             if(x>y)swap(x,y);    //注意这里,坑
63             if(op==0){
64                 update(1,1,n,x,y);
65             }
66             else{
67                 printf("%lld\n",query(1,1,n,x,y));
68             }
69         }
70         printf("\n");
71     }
72     return 0;
73 }

 

 

2018-09-23

posted @ 2018-09-23 17:06  悠悠呦~  阅读(197)  评论(0编辑  收藏  举报
浏览器标题切换
浏览器标题切换end