源代码: #include<cstdio> int n,num(0),h[100001]; struct treetype { int left,right,lefts,rights,sum,sign; }i[200020]; void x1(int t1,int t2) //建树。 { int t=++num; i[t].left=t1; i[t].right=t2; if (t1!=t2-1) { i[t].lefts=num+1; x1(t1,(t1+t2)/2); i[t].rights=num+1; x1((t1+t2)/2,t2); i[t].sum=i[i[t].lefts].sum+i[i[t].rights].sum; } else i[t].sum=h[t1]; } void lazy(int t) //利用省劲的懒惰算法,向下加深一层。 { i[i[t].lefts].sum+=i[t].sign*(i[i[t].lefts].right-i[i[t].lefts].left); i[i[t].rights].sum+=i[t].sign*(i[i[t].rights].right-i[i[t].rights].left); i[i[t].lefts].sign+=i[t].sign; i[i[t].rights].sign+=i[t].sign; i[t].sign=0; } void x2(int t,int x,int y,int z) { if (x<=i[t].left&&y>=i[t].right) { i[t].sum+=z*(i[t].right-i[t].left); i[t].sign+=z; //可能还留有处理过的标记,故应进行叠加。 } else { if (i[t].sign) //为继续向下搜索,进行提前准备。 lazy(t); if (x<(i[t].left+i[t].right)/2) x2(i[t].lefts,x,y,z); if (y>(i[t].left+i[t].right)/2) x2(i[t].rights,x,y,z); i[t].sum=i[i[t].lefts].sum+i[i[t].rights].sum; } } int x3(int t,int x,int y) //求和。 { if (x<=i[t].left&&y>=i[t].right) return i[t].sum; if (i[t].sign) //同理于上,为继续向下搜索,进行提前准备。 lazy(t); int ans(0); if (x<(i[t].left+i[t].right)/2) ans+=x3(i[t].lefts,x,y); if (y>(i[t].left+i[t].right)/2) ans+=x3(i[t].rights,x,y); return ans; } int main() { scanf("%d",&n); for (int a=1;a<=n;a++) scanf("%d",&h[a]); x1(1,n+1); scanf("%d",&n); for (int a=1;a<=n;a++) { int t; scanf("%d",&t); if (t==1) { int x,y,z; scanf("%d%d%d",&x,&y,&z); //进行区间范围的修改。 x2(1,x,y+1,z); //以半闭半开区间形式进行处理。 } else { int x,y; scanf("%d%d",&x,&y); printf("%d\n",x3(1,x,y+1)); //同理于上,以半闭半开区间形式进行处理。 } } return 0; }
转载于:https://www.cnblogs.com/koruko/p/5189063.html