模板:线段树
来源:互联网 发布:python 均线策略 编辑:程序博客网 时间:2024/06/16 11:56
/*单点更新,区间求和*//*应用:1.建空树,可以查询比某值大的数之和,然后单点更新*/#define N 50050 int num[N]; struct Tree{ int l; int r; int sum; }tree[4*N]; void build(int t,int l,int r){ tree[t].l=l; tree[t].r=r; if(tree[t].l==tree[t].r){ tree[t].sum=num[l]; return; } int mid=(l+r)/2; build(2*t,l,mid); build(2*t+1,mid+1,r); tree[t].sum=tree[2*t].sum+tree[2*t+1].sum;} void update(int t,int pos,int val){ if(tree[t].l==tree[t].r){ tree[t].sum=val; return; } int mid=(tree[t].l+tree[t].r)/2; if(pos<=mid) /*这点注意,我们都把mid放到左边了*/ update(2*t,pos,val); else update(2*t+1,pos,val); tree[t].sum=tree[2*t].sum+tree[2*t+1].sum;} int query(int t,int l,int r){ if(l<=tree[t].l&&r>=tree[t].r) return tree[t].sum; int mid=(tree[t].l+tree[t].r)/2,ans=0; if(l<=mid) ans+=query(2*t,l,r);/*加完左边加上右边的,不用分情况考虑*/ if(r>mid) ans+=query(2*t+1,l,r); return ans; } /*单点更新,区间最值*/void build(int t,int l,int r){ tree[t].l=l; tree[t].r=r; if(l==r){ tree[t].max=num[l]; return; } int mid=(l+r)/2; build(2*t,l,mid); build(2*t+1,mid+1,r); tree[t].max=Max(tree[2*t].max,tree[2*t+1].max); } void update(int t,int pos,int x){ if(tree[t].l==tree[t].r){ tree[t].max=x; return; } int mid=(tree[t].l+tree[t].r)/2; if(pos<=mid){ update(2*t,pos,x); } else update(2*t+1,pos,x); tree[t].max=Max(tree[2*t].max,tree[2*t+1].max); } int query(int t,int l,int r){ if(l<=tree[t].l&&r>=tree[t].r) return tree[t].max; int s; if(r<=tree[2*t].r) s=query(2*t,l,r); else if(l>=tree[2*t+1].l) s=query(2*t+1,l,r); else s=Max(query(2*t,l,tree[2*t].r),query(2*t+1,tree[2*t+1].l,r)); return s; }
区间更新,区间求和(延迟标记)
#define ll long longconst int maxn = 111111;ll num[maxn<<2];struct Tree{ int l,r; ll sum;}tree[maxn<<2];ll lazy[maxn<<2];void down(int t, int len){ if(lazy[t]){ lazy[t<<1] += lazy[t]; lazy[t<<1|1] += lazy[t];/*延迟标记往下传*/ tree[t<<1].sum += lazy[t] * (len-(len>>1));/*左子树比右子树多1*/ tree[t<<1|1].sum += lazy[t] * (len>>1); lazy[t] = 0; /*往下传完就赋0*/ }}void build(int l,int r,int t){ tree[t].l=l; tree[t].r=r; lazy[t]=0; if(l==r){ tree[t].sum=num[l]; return; } int mid=(l+r)>>1; build(l,mid,t<<1); build(mid+1,r,t<<1|1); tree[t].sum=tree[2*t].sum+tree[2*t+1].sum;}void update(int x,int l,int r,int t){ if(l<=tree[t].l&&r>=tree[t].r){ lazy[t]+=x; tree[t].sum+=(ll)x*(tree[t].r-tree[t].l+1); return; } down(t,tree[t].r-tree[t].l+1); int mid=(tree[t].l+tree[t].r)>>1; if(l<=mid) update(x,l,r,t<<1); if(r>mid) update(x,l,r,t<<1|1); tree[t].sum=tree[2*t].sum+tree[2*t+1].sum;}ll query(int l,int r,int t){ if(l<=tree[t].l&&r>=tree[t].r) return tree[t].sum; down(t,tree[t].r-tree[t].l+1); int mid=(tree[t].l+tree[t].r)>>1; ll ans=0; if(l<=mid) ans+=query(l,r,2*t);/*加完左边加上右边的,不用分情况考虑*/ if(r>mid) ans+=query(l,r,2*t+1); return ans;}更新节点,区间合并(push_up)
const int N=100005;int n,m,s[N];struct Tree{ int l,r,c;//左右边界与连续的长度 int ln,rn;//左右边界的值 int ls,rs,ms;//左右最大LCIS,和区间最大LCIS }tree[4*N]; void push_up(int i){ tree[i].ls = tree[2*i].ls; tree[i].rs = tree[2*i+1].rs; tree[i].ln = tree[2*i].ln; tree[i].rn = tree[2*i+1].rn; tree[i].ms = max(tree[2*i].ms,tree[2*i+1].ms); if(tree[2*i].rn<tree[2*i+1].ln){ //如果左子树的右边界值小于右子树的左边界值,要合并左子树的右边界和右子树的左边界 if(tree[2*i].ls == tree[2*i].c) tree[i].ls+=tree[2*i+1].ls; if(tree[2*i+1].rs == tree[2*i+1].c) tree[i].rs+=tree[2*i].rs; tree[i].ms = max(tree[i].ms,tree[2*i].rs+tree[2*i+1].ls); } } void build(int t,int l,int r){ tree[t].l=l; tree[t].r=r; tree[t].c=r-l+1; if(l==r){ tree[t].ln=tree[t].rn=s[l]; tree[t].ls=tree[t].rs=tree[t].ms=1; return; } int mid=(l+r)>>1; build(2*t,l,mid); build(2*t+1,mid+1,r); push_up(t); } void update(int t,int pos,int val){ if(tree[t].l==tree[t].r){ tree[t].ln=tree[t].rn=val; return; } int mid=(tree[t].l+tree[t].r)>>1; if(pos<=mid) update(2*t,pos,val); else update(2*t+1,pos,val); push_up(t); //向上维护 } int query(int t,int l,int r){ if(l<=tree[t].l&&r>=tree[t].r) return tree[t].ms; int mid=(tree[t].l+tree[t].r)>>1,ans=0; if(l<=mid) ans=max(ans,query(2*t,l,r)); if(r>mid) ans=max(ans,query(2*t+1,l,r)); if(tree[2*t].rn < tree[2*t+1].ln) ans=max(ans, min(mid-l+1,tree[2*t].rs) + min(r-mid,tree[2*t+1].ls)); //不能超过边界啊,所以右边要小于r-mid,左边同理。 return ans; }区间合并(up and down)
/*lsum数组表示该段rt区间的左连续区间的最大值rsum数组表示该段rt区间的右连续区间的最大值msum数组表示该段区间的连续区间的最大值,可以是左连续、右连续、也可以使中间连续lazy数组表示懒惰标记,-1时表示未打上懒惰标记,不需要改变,0时表示该区间打上了区间被使用,1表示该区间被回收*/const int maxn = 5e4+5; int msum[maxn<<2],lsum[maxn<<2],rsum[maxn<<2]; int lazy[maxn<<2]; void up(int l,int r,int rt){ int mid=(l+r)>>1; lsum[rt]=lsum[rt<<1]; rsum[rt]=rsum[rt<<1|1]; if(lsum[rt<<1]==mid-l+1) lsum[rt]+=lsum[rt<<1|1]; if(rsum[rt<<1|1]==r-mid) rsum[rt]+=rsum[rt<<1]; msum[rt]=max(rsum[rt<<1]+lsum[rt<<1|1],max(msum[rt<<1],msum[rt<<1|1])); } void down(int l,int r,int rt){ if(lazy[rt]!=-1){ int mid=(l+r)>>1; lazy[rt<<1]=lazy[rt<<1|1]=lazy[rt]; msum[rt<<1]=lsum[rt<<1]=rsum[rt<<1]=lazy[rt]?mid-l+1:0; msum[rt<<1|1]=lsum[rt<<1|1]=rsum[rt<<1|1]=lazy[rt]?r-mid:0; lazy[rt]=-1; } } void build(int l,int r,int rt){ lazy[rt]=-1; msum[rt]=lsum[rt]=rsum[rt]=r-l+1; if(l==r) return; int mid=(l+r)>>1; build(l,mid,rt<<1); build(mid+1,r,rt<<1|1); } void update(int L,int R,int k,int l,int r,int rt){ if(L<=l&&r<=R){ lazy[rt]=k; msum[rt]=lsum[rt]=rsum[rt]=k?r-l+1:0; return; } down(l,r,rt); int mid=(l+r)>>1; if(L<=mid) update(L,R,k,l,mid,rt<<1); if(R>mid)update(L,R,k,mid+1,r,rt<<1|1); up(l,r,rt); } int query(int len,int l,int r,int rt){ if(l==r) return l; down(l,r,rt); int mid=(l+r)>>1; if(msum[rt<<1]>=len) return query(len,l,mid,rt<<1); else if(rsum[rt<<1]+lsum[rt<<1|1]>=len) return mid-rsum[rt<<1]+1; else return query(len,mid+1,r,rt<<1|1); }
阅读全文
0 0
- ACM 线段树模板(模板)
- 线段树模板
- hdu_1166_线段树模板
- 线段树模板
- 线段树模板 poj2777
- 线段树模板
- 线段树模板
- 线段树-模板
- 线段树模板
- 线段树模板
- 线段树模板
- Hdu1166-- 线段树模板
- 线段树模板
- 线段树模板
- 线段树模板
- 线段树模板
- 线段树模板
- 线段树模板
- iOS-野指针定位
- 线性表综合实验--双链表
- 【Linux内核】体系结构
- cdh vm使用
- 模拟登录上海交大Jaccount
- 模板:线段树
- 如何在NumPy中创建空数组/矩阵?
- 疯狂的采药(完全背包模板)
- JavaWeb框架-Struts2-2-帅气滴Struts2!
- python: 从字符串中提取数字
- 抽象工厂
- java学习笔记
- 教你如何快速高效的提高收入,不要一味地跳槽!
- 基于Vue2的移动端开发环境搭建详解