462 字
2 分钟
4-2数据结构
数据结构(二)
Part 7.8 线段树 Part 7.9 分块 Part 7.10 可并堆 Part 7.11 主席树 Part 7.12 平衡树
Part 7.8 线段树
线段树 (区间修改,区间覆盖)
ps:
区间修改,区间查询。 dug功能输出树
struct my_tree{ #define kl (k<<1) #define kr (k<<1|1)
struct node { int l, r, sum; int lz; }; vector<node> tree;
my_tree(int x,ve<int>&a) { tree = vector<node>(x*4+10); build(1,1,x,a); }
void pushup(node& kk, const node& kkl, const node& kkr) { kk.sum = max(kkl.sum, kkr.sum); } void pushup(int k) { pushup(tree[k], tree[kl], tree[kr]); }
void pushdown(int k) { if(tree[k].lz==0) return ; tree[kl].sum=tree[kr].sum=tree[k].lz; tree[kl].lz=tree[kr].lz=tree[k].lz; tree[k].lz=0; }
void build(int k, int l, int r, ve<int>& a) { tree[k].l = l; tree[k].r = r; if (l == r) { tree[k].sum = a[l]; return; } int mid = (l + r) >> 1; build(kl, l, mid, a); build(kr, mid + 1, r, a); pushup(k); }
// 区间修改 区间修改 [l,r] 全复制成val void update(int k, int l, int r, int val) { if (tree[k].l >= l && tree[k].r <= r) { tree[k].sum = val; tree[k].lz=val; return; } pushdown(k); int mid = (tree[k].l + tree[k].r) >> 1; if (l <= mid) update(kl, l, r, val); if (r > mid) update(kr, l, r, val); pushup(k); }
node query(int k, int l, int r) { if (l <= tree[k].l && tree[k].r <= r) return tree[k]; pusgdown(k);
int mid = (tree[k].l + tree[k].r) >> 1;
node kkl = {tree[k].l, mid}; node kkr = {mid + 1, tree[k].r}; node kk = {tree[k].l, tree[k].r};
int opl=0,opr=0; if (l <= mid) kkl = query(kl, l, r),opl=1; if (r > mid) kkr = query(kr, l, r),opr=1; if(opl&&opr) { pushup(kk, kkl, kkr); return kk; } if(opl) return kkl; return kkr; }
void dug(int k=1) { auto [l,r,sum,lz]=tree[k]; cout<<"k: "<<k<<"\n"; cout<<"[ "<<l<<" "<<r<<" "<<sum<<" "<<lz<<" ]"<<'\n'; if(l<r) { dug(kl); dug(kr); } }};权值线段树
单点修改,区间查询个数 权值线段树的每一个节点,存放的是[l,r]的值个数
#define kl (k<<1)#define kr (k<<1|1)
struct node{ int l,r; int sum;}tre[N*4+10];
void build(int k,int l,int r){ tre[k]={l,r}; if(l==r) return ; int mid=(l+r)>>1; build(kl,l,mid); build(kr,mid+1,r);}
void insert(int k,int val,int id){ tre[k].sum+=id; if(tre[k].l==tre[k].r) return ; int mid=(tre[k].l+tre[k].r)>>1; if(val<=mid) insert(kl,val,id); else insert(kr,val,id);}
int query(int k,int l,int r){ if(l<=tre[k].l&&tre[k].r<=r) return tre[k].sum; int mid=(tre[k].l+tre[k].r)>>1; int ans=0; if(l<=mid) ans+=query(kl,l,r); if(r>mid) ans+=query(kr,l,r); return ans;}动态开点线段树