题目链接: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; }