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
作者:is_ok
出处:http://www.cnblogs.com/00isok/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。