简单的线段树
2017-11-07 21:10
127 查看
前言
线段树想必大家再熟悉不过了,说实话敲线段树的模板还是很享受的(温馨提示:不要被数据结构所驾驭了)。这里,蒟蒻我就简要说一下鄙人的线段树的一些简单功能:支持单点、区间更新,求单点权值,区间求和、最值。
struct Tree{ #define lson L,mid,p<<1 #define rson mid+1,R,p<<1|1 #define family tree[p],tree[p<<1],tree[p<<1|1] #define root 1,n,1 struct node{ int L,R; int sum,add; int Mx,Mn; }tree[N<<2]; void Up(node &A,node L,node R){ A.sum=L.sum+R.sum; A.Mx=max(L.Mx,R.Mx); A.Mn=min(L.Mn,R.Mn); } void Down(node &A,node &L,node &R){ int &t=A.add; if(!t)return; L.add+=t; R.add+=t; L.sum+=t*(L.R-L.L+1); R.sum+=t*(R.R-R.L+1); t=0; } void build(int L,int R,int p){ tree[p].L=L,tree[p].R=R; tree[p].sum=tree[p].add=0; if(L==R){ // tree[p].sum=A[L]; return; } int mid=(L+R)>>1; build(lson),build(rson); Up(family); } void update_one(int x,int res,int p){ if(tree[p].L==tree[p].R){ tree[p].sum+=res; return; } int mid=(tree[p].L+tree[p].R)>>1; if(x<=mid)update_one(x,res,p<<1); else update_one(x,res,p<<1|1); Up(family); } void update_interval(int L,int R,int p,int res){ if(tree[p].L==L && tree[p].R==R){ tree[p].add+=res; tree[p].sum+=1LL*res*(R-L+1); return; } Down(family); int mid=(tree[p].L+tree[p].R)>>1; if(R<=mid)update_interval(L,R,p<<1,res); else if(L>mid)update_interval(L,R,p<<1|1,res); else update_interval(lson,res),update_interval(rson,res); Up(family); } //注意求单点只需要沿途加上sum即可,不用Down int query_one(int x,int p){ int mid=(tree[p].L+tree[p].R)>>1; if(x<=mid)return tree[p].sum+query_one(x,p<<1); else return tree[p].sum+query_one(x,p<<1|1); } int query_interval(int L,int R,int p){ if(tree[p].L==L && tree[p].R==R)return tree[p].sum; Down(family); int mid=(tree[p].L+tree[p].R)>>1; if(R<=mid)return query_interval(L,R,p<<1); else if(L>mid)return query_interval(L,R,p<<1|1); else return query_interval(lson)+query_interval(rson); } int query_Max(int L,int R,int p){ if(tree[p].L==L && tree[p].R==R)return tree[p].Mx; int mid=(tree[p].L+tree[p].R)>>1; if(R<=mid)return query_Max(L,R,p<<1); else if(L>mid)return query_Max(L,R,p<<1|1); else return max(query_Max(lson),query_Max(rson)); } int query_Min(int L,int R,int p){ if(tree[p].L==L && tree[p].R==R)return tree[p].Mn; int mid=(tree[p].L+tree[p].R)>>1; if(R<=mid)return query_Min(L,R,p<<1); else if(L>mid)return query_Min(L,R,p<<1|1); else return min(query_Min(lson),query_Min(rson)); } }Tree;
小结:
线段树是一个非常好用的东西,是常用于维护区间的某些值的数据结构之一。
相关文章推荐
- 线段树简单实现
- 敌兵布阵(简单线段树)
- poj 1436 Horizontally Visible Segments(线段树成段覆盖问题+简单hash),好题,覆盖问题想法较难
- 线段树 HDU 1754 最简单的线段树
- HDU1166敌兵布阵 简单线段树
- 线段树之简单方法
- POJ 3667 线段树的区间合并简单问题
- [线段树][简单复杂度分析]LOJ#6029. 「雅礼集训 2017 Day1」市场
- HDU 1754 I hate it 【线段树简单题】
- codeforces 339D 简单的线段树操作
- 【线段树 + 简单题】杭电 hdu 1166 敌兵布阵
- HDU 1754 ——简单线段树
- P1531 I Hate It(最简单的线段树)
- POJ 1436——Horizontally Visible Segments(线段树,区间染色+暴力+简单hash)
- ZOJ 3349 Special Subsequence 简单DP + 线段树
- UVa 12299 - RMQ with Shifts (简单线段树)
- POJ 3264 简单线段树
- 2018年全国多校算法寒假训练营练习比赛(第五场)B(简单线段树)
- (简单) POJ 3667 Hotel,线段树+区间合并。
- POJ 2777——Count Color(线段树,区间染色+简单hash)