HDU - 4027 Can you answer these queries? (线段树)
Posted ljwcarrot
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU - 4027 Can you answer these queries? (线段树)相关的知识,希望对你有一定的参考价值。
题目传送门:HDU - 4027 Can you answer these queries?
题目大意:
存在n艘敌军战舰,每艘战舰都有能量值,我军存在一种秘密武器,每次能够将在该区间内的所
有战舰的能量值开方,现在指挥官想要知道武器的效果,需要你告诉他该区间内敌军战舰的能
量值之和
分析:
该题对区间进行操作,显然是用线段树。两个操作分别是对区间进行开方和区间求和,对区间中战舰的能量值
进行开方操作,很简单的会想到用lazy数组,但会发现无法像区间加减写出类似的式子。仔细想便可发现数据
最大值为2 63,因此没个数最多能开6-7次方,之后1开方仍然为1.因此如果一个区间中的值全为1,则他就不需
要再进行任何操作即可。若区间不满足条件则进行单点更新,将每个值开方即可。区间求和就是很普通的区间
求和了
//判断区间是否全为1 if(sum[rt]==r-l+1)return;
代码:
#include<iostream> #include<cstring> #include<cmath> #include<cstdio> using namespace std; #define ls l,m,rt<<1 #define rs m+1,r,rt<<1|1 typedef long long ll; const int MAX=100009; int n,m,t,x,y; ll sum[MAX<<2]; void PushUp(int rt) { sum[rt]=sum[rt<<1]+sum[rt<<1|1]; } void Build(int l,int r,int rt) { if(l==r) { scanf("%lld",&sum[rt]); return; } int m=l+r>>1; Build(ls); Build(rs); PushUp(rt); } void Update(int L,int R,int l,int r,int rt) { if(sum[rt]==r-l+1)return; //判断区间是否全为1 if(l==r) { sum[rt]=(ll)(sqrt(sum[rt])); //直接开方即可 return; } int m=(l+r)>>1; if(L<=m)Update(L,R,ls); if(R>m)Update(L,R,rs); PushUp(rt); } ll Query(int L,int R,int l,int r,int rt) { if(L<=l&&r<=R) { return sum[rt]; } int m=l+r>>1; ll ans=0; if(L<=m)ans+=Query(L,R,ls); if(R>m)ans+=Query(L,R,rs); return ans; } int main() { int f=1; while(scanf("%d",&n)!=EOF) { printf("Case #%d: ",f++); memset(sum,0,sizeof(sum)); Build(1,n,1); scanf("%d",&m); while(m--) { scanf("%d%d%d",&t,&x,&y); if(x>y)swap(x,y); if(t==0) Update(x,y,1,n,1); if(t==1) printf("%lld ",Query(x,y,1,n,1)); } printf(" "); } return 0; }
以上是关于HDU - 4027 Can you answer these queries? (线段树)的主要内容,如果未能解决你的问题,请参考以下文章
HDU 4027 Can you answer these queries? (线段树)
HDU-4027 Can you answer these queries?(线段树区间开方)
HDU 4027 Can you answer these queries?
Can you answer these queries? HDU - 4027