题意:

给你n个数,两个操作,0为区间开方,1为区间求和

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

思路:

如果当该区间的数都为1,我们没必要进行开方操作,因为1开方还是1,否则找到每个叶子节点,进行开方操作

代码:

#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstdlib>
using namespace std;
const int MAXN=1e5+;
const int INF=0x7fffffff;
typedef long long ll;
ll lazy[MAXN<<],tree[MAXN<<];
void push_up(int node)
{
tree[node]=tree[node<<]+tree[node<<|];
}
void build(int node,int l,int r)
{
if(l==r)
{
scanf("%lld",&tree[node]);
return ;
}
int mid=(l+r)>>;
build(node<<,l,mid);
build(node<<|,mid+,r);
push_up(node);
} void update(int node,int l,int r,int x,int y)
{
//区间的长度等于区间内所有数之和则说明所有数都为1
if(x<=l&&y>=r&&(r-l+==tree[node]))
{
return;
}
if(l==r)
{
tree[node]=(ll)sqrt(tree[node]);return;
}
int mid=(l+r)>>;
if(x<=mid)
update(node<<,l,mid,x,y);
if(y>mid)
update(node<<|,mid+,r,x,y);
push_up(node);
}
ll query(int node,int l,int r,int x,int y)
{
if(x<=l&&y>=r)
{
return tree[node];
}
ll ans=;
int mid=(l+r)>>;
if(x<=mid)ans+=query(node<<,l,mid,x,y);
if(y>mid)ans+=query(node<<|,mid+,r,x,y);
return ans;
}
int main()
{
int n;
int case_=;
while(scanf("%d",&n)!=EOF)
{
printf("Case #%d:\n",++case_);
build(,,n);
int k;scanf("%d",&k);
for(int i=;i<=k;i++)
{
int op;scanf("%d",&op);
int x,y;
if(!op)
{
scanf("%d%d",&x,&y);update(,,n,min(x,y),max(x,y));
}
else
{
scanf("%d%d",&x,&y);
printf("%lld\n",query(,,n,min(x,y),max(x,y)));
} }printf("\n");
} return ;
}
05-21 07:22