题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4027
懒人标记法 注意更新的方法
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#define N 10000000
#define L(x) x<<1
#define R(x) x<<1|1
struct node{
int l,r,mid;
bool flag;
__int64 sum;
}tree[N*3];
__int64 a[N];
void build(int l,int r, int id){
tree[id].l=l; tree[id].r=r; tree[id].mid=(l+r)>>1;
tree[id].flag=1;
if(l==r)
{
tree[id].sum=a[l];
if(a[l]<=1) tree[id].flag=0;
return ;
}
build(l,tree[id].mid,L(id));
build(tree[id].mid+1,r,R(id));
tree[id].sum=tree[L(id)].sum+tree[R(id)].sum;
tree[id].flag=tree[L(id)].flag || tree[R(id)].flag;
}
void update(int l,int r,int id)
{
if(tree[id].flag==0)return;
if(tree[id].l==tree[id].r && tree[id].l==l &&tree[id].r==r) //必须开根号到最后一层,所以加tree[].l==tree[].r
{
tree[id].sum=(__int64)sqrt(1.0*tree[id].sum);//注意这样才不会根号开出0来
if(tree[id].sum<=1) tree[id].flag=0; //标记为0 就不找了
return ;
}
if(r<=tree[id].mid)
update(l,r,L(id));
else if(l>tree[id].mid)
update(l,r,R(id));
else
{
update(l,tree[id].mid,L(id));
update(tree[id].mid+1,r,R(id));
}
tree[id].sum=tree[id<<1].sum+tree[id<<1|1].sum;
tree[id].flag=tree[id<<1].flag||tree[id<<1|1].flag;//如果子节点有未更新的则父节点必须更新
}
__int64 find(int l,int r, int id){
if(tree[id].l==l && tree[id].r==r) return tree[id].sum;
__int64 ans=0;
if(r<=tree[id].mid)ans+=find(l,r,L(id));
else if(l>tree[id].mid)ans+=find(l,r,R(id));
else
ans+=( find(l,tree[id].mid,L(id))+ find(tree[id].mid+1,r,R(id)) );
return ans;
}
int main(){
int n,num=1;
while(~scanf("%d",&n)){
for(int i=1;i<=n;i++)
scanf("%I64d",&a[i]);
build(1,n,1);
int k; scanf("%d",&k);
printf("Case #%d:\n",num++);
while(k--){
int oper,a,b;
scanf("%d %d %d",&oper,&a,&b);
int x=a>b?b:a,y=a>b?a:b;
switch(oper)
{
case 1:printf("%I64d\n",find(x,y,1)); break;
case 0:update(x,y,1); break;
}
}
printf("\n");
}
return 0;
}