线段树
参考博客:线段树详解
模板:
#define Mid ((l+r)>>1) //注意括号 #define lson rt<<1,l,Mid //左结点 #define rson rt<<1|1,Mid+1,r //右结点
//线段树模板(单点更新) #define Mid ((l+r)>>1) #define lson rt<<1,l,Mid #define rson rt<<1|1,Mid+1,r const int maxn = 100010; int sum[maxn<<2]; void build(int rt,int l,int r) { if(l==r){ scanf("%d",&sum[rt]); }else{ build(lson); build(rson); sum[rt] = sum[rt<<1] + sum[rt<<1|1]; } } void update(int rt,int l,int r,int pos,int num) //修改pos位值为num { if(l == r && r == pos){ sum[rt] += num; }else{ if( pos <= Mid) update(lson,pos,num); else update(rson,pos,num); sum[rt] = sum[rt<<1] + sum[rt<<1|1]; } } int query(int rt,int l,int r,int L,int R) //查询[L,R] { if(L <= l && r <= R){ return sum[rt]; }else{ int tmp = 0; if( L <= Mid) tmp += query(lson,L,R); if( R > Mid) tmp += query(rson,L,R); return tmp; } }
//线段树模板(区间更新) #define Mid ((l+r)>>1) #define lson rt<<1,l,Mid #define rson rt<<1|1,Mid+1,r const int maxn = 100010; int sum[maxn<<2],add[maxn<<2]; void build(int rt,int l,int r) { add[rt] = 0; if(l == r){ scanf("%d",&sum[rt]); //省个数组 }else{ build(lson); build(rson); sum[rt]=sum[rt<<1]+sum[rt<<1|1]; } } void pushDown(int rt,int len) { add[rt<<1] = add[rt<<1|1] = add[rt]; sum[rt<<1] = (len-(len>>1))*add[rt]; sum[rt<<1|1] = (len>>1)*add[rt]; add[rt] = 0; } void update(int rt,int l,int r,int L,int R,int z) //更新[L,R]为z { if(L <= l && r <= R){ add[rt] = z; sum[rt] = (r-l+1)*z; }else{ if(add[rt]) pushDown(rt,r-l+1); if(L <= Mid) update(lson,L,R,z); if(R > Mid) update(rson,L,R,z); sum[rt] = sum[rt<<1] + sum[rt<<1|1]; } } int query(int rt,int l,int r,int L,int R) //查询[L,R],调用:(1,1,n,L,R) { if(L <= l && r <= R){ return sum[rt]; }else{ if(add[rt]) pushDown(rt,r-l+1); int t = 0; if(L <= Mid) t += query(lson,L,R); if(R > Mid) t += query(rson,L,R); return t; } }
//建树 Build(1,n,1); //点修改 Update(L,C,1,n,1); //区间修改 Update(L,R,C,1,n,1); //区间查询 int ANS=Query(L,R,1,n,1);