二话不说,直接上代码!(懒)
#include<stdio.h> #include<algorithm> using namespace std; #define Maxx 1000000 struct Tree{ int l,r,sum; }t[4*Maxx];//开四倍空间,防爆 int a[Maxx],add[Maxx],sum[Maxx];//sum每个节点的子节点数值的总和,add该节点的每个数值应该加多少 int len; void built_tree(int i,int l,int r){//简单建树 t[i].l=l; t[i].r=r; if(l==r){ t[i].sum=a[l]; return; } int mid=(l+r)/2; built_tree(i*2+1,l,mid);//left built_tree(i*2+2,mid+1,r);//right t[i].sum=t[i*2+1].sum+t[i*2+2].sum; } void pushdown(int i,int m){//向下更新 //从根节点i向下更新每个子节点的值,m为子节点个数 if(add[i]){//判断是否有标记 add[i*2+1]+=add[i];//+=特别注意,debug警告! add[i*2+2]+=add[i]; t[i*2+1].sum+=add[i]*(m-(m>>1));//毕竟奇数时左边的比右边多个数 t[i*2+2].sum+=add[i]*(m>>1); add[i]=0;//还原 } } void chang_point(int i,int l,int r,int num,int x){//单点修改 if(l==r){//num位置上的数加上x t[i].sum+=x; return; } pushdown(i,t[i].r-t[i].l+1);//向下更新 int mid=(l+r)/2; if(num<=mid) chang_point(i*2+1,l,mid,num,x);//在左边 else chang_point(i*2+2,mid+1,r,num,x);//在右边 } int search_sum(int i,int l,int r){//区间查询 int s=0; if(t[i].l>r || t[i].r<l){//不在范围 return 0; } if(t[i].l>=l && t[i].r<=r){//(l,r)完全包含该节点,因此为s的一部分。 return t[i].sum; } pushdown(i,t[i].r-t[i].l+1);//遇到标记向下更新 int mid=(t[i].l+t[i].r)/2; if(r<=mid){ s+=search_sum(i*2+1,l,r);//完全在节点左边 }else if(l>mid){//debug>好久(mid在左区间) s+=search_sum(i*2+2,l,r);//完全在节点右边 }else{//部分在左部分在右 s+=search_sum(i*2+1,l,mid); s+=search_sum(i*2+2,mid+1,r); } return s; } void update(int i,int l,int r,int num){//区间修改 //[l,r]每个数加num if(t[i].l==l && t[i].r==r){//提前结束 add[i]+=num;//多次操作存在提前结束在同一个节点上,需要累加,+=! t[i].sum+=num*(r-l+1);//[l,r]每个数加num == 节点个数*num return; } if(t[i].l==t[i].r) return;//最低了,不能再下了! pushdown(i,t[i].r-t[i].l+1);//向下更新 int mid=(t[i].l+t[i].r)/2; if(r<=mid){//完全在左 update(i*2+1,l,r,num); }else if(l>mid){//完全在右 update(i*2+2,l,r,num); }else{//左右都有一部分 update(i*2+1,l,mid,num);//搜索左边 update(i*2+2,mid+1,r,num);//搜索右边 } t[i].sum=t[i*2+1].sum+t[i*2+2].sum; } int main() { scanf("%d",&len); for(int i=0;i<len;i++){ scanf("%d",&a[i]);//1 5 6 8 9 12 35 4 7 } built_tree(0,0,len-1);//建树 int sumlr=search_sum(0,1,3);//查询区间和 printf("%d ",sumlr); update(0,1,3,5);//区间加数 int sumlr2=search_sum(0,1,3); printf("%d ",sumlr2); }
请忽略命名和码风那些,毕竟纯手打,临时编的变量名,怎么简单怎么来╰(*°▽°*)╯
原文:https://www.cnblogs.com/sizhen/p/12782071.html