線段樹點更新,區間更新
阿新 • • 發佈:2018-11-09
點更新:
const int N=1005; #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 int sum[N<<2],n; void Push_up(int rt){ sum[rt]=sum[rt<<1]+sum[rt<<1|1]; } void Build(int l,int r,int rt){ if(l==r){sum[rt]=a[l];return ;} int m=(l+r)>>1;//以rt為根,子區間的介面處 Build(lson); Build(rson); Push_up(rt); } //點修改A[P]+=C; void Update(int P,int C,int l,int r,int rt){ if(l==r){sum[rt]+=C;return ;}//到達葉節點,修改葉節點的值 int m=(l+r)>>1; //根據條件判斷往左子樹呼叫還是右子樹 if(P<=m)Update(P,C,lson);//P點在左子樹就去更新左子樹 else Update(P,C,rson); Push_up(rt); } int Query(int L,int R,int l,int r,int rt){ if(L<=l&&r<=R){ return sum[rt]; } int m=(l+r)>>1; int ans=0; if(L<=m)ans+=Query(L,R,lson); if(R>m)ans+=Query(L,R,rson); return ans; }
區間更新:
const int N=1005; #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 int sum[N<<2],add[N<<2],n; void Push_up(int rt){ sum[rt]=sum[rt<<1]+sum[rt<<1|1]; } void Build(int l,int r,int rt){ if(l==r){sum[rt]=a[l];return ;} int m=(l+r)>>1;//以rt為根,子區間的介面處 Build(lson); Build(rson); Push_up(rt); } void Push_down(int rt,int ln,int rn){ if(add[rt]){ add[rt<<1]+=add[rt]; add[rt<<1|1]+=add[rt]; sum[rt<<1]+=add[rt]*ln; sum[rt<<1|1]+=add[rt]*rn; add[rt]=0; } } //區間修改A[l,r]+=C; void Update(int L,int R,int C,int l,int r,int rt){ if(L<=l&&r<=R){ sum[rt]+=C*(r-l+1); add[rt]+=C; return ; } int m=(l+r)>>1; Push_down(rt,m-l+1,r-m); //根據條件判斷往左子樹呼叫還是右子樹 if(L<=m)Update(L,R,C,lson); if(R>m) Update(L,R,C,rson); Push_up(rt); } int Query(int L,int R,int l,int r,int rt){ if(L<=l&&r<=R){ return sum[rt]; } int m=(l+r)>>1; Push_down(rt,m-l+1,r-m); int ans=0; if(L<=m)ans+=Query(L,R,lson); if(R>m)ans+=Query(L,R,rson); return ans; }
注意點和區間更新時update函式的差別~