1、线段树html
http://www.cnblogs.com/TheRoadToTheGold/p/6254255.htmlnode
一、建树,即创建一棵线段树ios
主体思路:a、对于二分到的每个结点,给它的左右端点肯定范围。ide
b、若是是叶子节点,存储要维护的信息。ui
c、状态合并。spa
void build(int k,int l,int r)//建树 { tree[k].l=l,tree[k].r=r; if(tree[k].l==tree[k].r) { tree[k].w=read(); return ; } int m=(l+r)>>1; build(k<<1,l,m); build(k<<1|1,m+1,r); tree[k].w=tree[k<<1].w+tree[k<<1|1].w; }
二、单点查询,即查询一个点的状态,设待查询点为xcode
主体思路:与二分查询法基本一致,若是当前枚举的点左右端点相等,即叶子节点,就是目标节点。若是不是,由于这是二分法,因此设查询位置为x,当前结点区间范围为了l,r,中点为 mid,则若是x<=mid,则递归它的左孩子,不然递归它的右孩子htm
void ask(int k) { if(tree[k].l==tree[k].r) //当前结点的左右端点相等,是叶子节点,是最终答案 { ans=tree[k].w; return ; } int m=(tree[k].l+tree[k].r)/2; if(x<=m) ask(k*2);//目标位置比中点靠左,就递归左孩子 else ask(k*2+1);//反之,递归右孩子 }
三、单点修改,即更改某一个点的状态。用引例中的例子,对第x个数加上yblog
主体思路 结合单点查询的原理,找到x的位置;根据建树状态合并的原理,修改每一个结点的状态。递归
void change_point(int k)//单点修改 { if(tree[k].l==tree[k].r) { tree[k].w+=y; return ; } if(tree[k].f) down(k); int m=(tree[k].l+tree[k].r)>>1; if(x<=m) change_point(k<<1); else change_point(k<<1|1); tree[k].w=tree[k<<1].w+tree[k<<1|1].w; }
4.区间修改+区间查询
void change_interval(int k)//区间修改 { if(tree[k].l>=a&&tree[k].r<=b) { tree[k].w+=y*(tree[k].r-tree[k].l+1); tree[k].f+=y; return ; } if(tree[k].f) down(k); int m=(tree[k].l+tree[k].r)>>1; if(a<=m) change_interval(k<<1); if(b>m) change_interval(k<<1|1); tree[k].w=tree[k<<1].w+tree[k<<1|1].w; } void ask_interval(int k)//区间查询 { if(tree[k].l>=a&&tree[k].r<=b) { ans+=tree[k].w; return ; } if(tree[k].f) down(k); int m=(tree[k].l+tree[k].r)>>1; if(a<=m) ask_interval(k<<1); if(b>m) ask_interval(k<<1|1); }
5.标记下传
实现思路
a.原结构体中增长新的变量,存储这个懒标记。
b.递归到这个节点时,只更新这个节点的状态,并把当前的更改值累积到标记中。注意是累积,能够这样理解:过年,不少个亲戚都给你压岁钱,但你暂时不用,因此都被你父母扣下了。
c.何时才用到这个懒标记?当须要递归这个节点的子节点时,标记下传给子节点。这里没必要管用哪一个子节点,两个都传下去。就像你若是还有妹妹,父母给大家零花钱时总不能偏爱吧
d.下传操做:
3部分:①当前节点的懒标记累积到子节点的懒标记中。
②修改子节点状态。在引例中,就是原状态+子节点区间点的个数*父节点传下来的懒标记。
void down(int k)//标记下传 { tree[k<<1].f+=tree[k].f; tree[k<<1|1].f+=tree[k].f; tree[k<<1].w+=tree[k].f*(tree[k<<1].r-tree[k<<1].l+1); tree[k<<1|1].w+=tree[k].f*(tree[k<<1|1].r-tree[k<<1|1].l+1); tree[k].f=0; }
#include<cstdio> #include<cstdlib> #include<cstring> #include<iostream> #include<algorithm> #define N 4000001 using namespace std; long long ans; int n,m,q,x,y,a,b; int read() { int x=0,f=1; char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1; ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0'; ch=getchar();} return x*f; } struct Tree { int l,r,f;long long w; }tree[N]; void build(int k,int l,int r)//建树 { tree[k].l=l,tree[k].r=r; if(tree[k].l==tree[k].r) { tree[k].w=read(); return ; } int m=(l+r)>>1; build(k<<1,l,m); build(k<<1|1,m+1,r); tree[k].w=tree[k<<1].w+tree[k<<1|1].w; } void down(int k)//标记下传 { tree[k<<1].f+=tree[k].f; tree[k<<1|1].f+=tree[k].f; tree[k<<1].w+=tree[k].f*(tree[k<<1].r-tree[k<<1].l+1); tree[k<<1|1].w+=tree[k].f*(tree[k<<1|1].r-tree[k<<1|1].l+1); tree[k].f=0; } void change_point(int k)//单点修改 { if(tree[k].l==tree[k].r) { tree[k].w+=y; return ; } if(tree[k].f) down(k); int m=(tree[k].l+tree[k].r)>>1; if(x<=m) change_point(k<<1); else change_point(k<<1|1); tree[k].w=tree[k<<1].w+tree[k<<1|1].w; } void ask_point(int k)//单点查询 { if(tree[k].l==tree[k].r) { ans=tree[k].w; return ; } if(tree[k].f) down(k); int m=(tree[k].l+tree[k].r)>>1; if(x<=m) ask_point(k<<1); else ask_point(k<<1|1); } void change_interval(int k)//区间修改 { if(tree[k].l>=a&&tree[k].r<=b) { tree[k].w+=y*(tree[k].r-tree[k].l+1); tree[k].f+=y; return ; } if(tree[k].f) down(k); int m=(tree[k].l+tree[k].r)>>1; if(a<=m) change_interval(k<<1); if(b>m) change_interval(k<<1|1); tree[k].w=tree[k<<1].w+tree[k<<1|1].w; } void ask_interval(int k)//区间查询 { if(tree[k].l>=a&&tree[k].r<=b) { ans+=tree[k].w; return ; } if(tree[k].f) down(k); int m=(tree[k].l+tree[k].r)>>1; if(a<=m) ask_interval(k<<1); if(b>m) ask_interval(k<<1|1); } int main() { n=read();m=read(); build(1,1,n); while(m--) { q=read();ans=0; if(q==1) { a=read(),b=read(),y=read(); change_interval(1); } else { a=read(),b=read(); ask_interval(1); printf("%lld\n",ans); } } return 0; }
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define N 100005 using namespace std; int n,m,c,a,b,x; long long ans,minn; int read() { int x=0,f=1; char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1; ch=getchar();} while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar(); return x*f; } struct Tree { int l,r; long long w,f; }tree[N<<2]; struct Node { int x,y,z; }node[N]; int cmp(Node a,Node b) { return a.y<b.y; } void build(int k,int l,int r) { tree[k].l=l,tree[k].r=r; if(tree[k].l==tree[k].r) { tree[k].w=c; return ; } int mid=(l+r)>>1; build(k<<1,l,mid); build(k<<1|1,mid+1,r); tree[k].w=min(tree[k<<1].w,tree[k<<1|1].w); } void down(int k) { tree[k<<1].f+=tree[k].f; tree[k<<1|1].f+=tree[k].f; tree[k<<1].w+=tree[k].f; tree[k<<1|1].w+=tree[k].f; tree[k].f=0; } void change(int k) { if(tree[k].l>=a&&tree[k].r<=b) { tree[k].w+=x; tree[k].f+=x; return ; } if(tree[k].f) down(k); int mid=(tree[k].r+tree[k].l)>>1; if(a<=mid) change(k<<1); if(b>mid) change(k<<1|1); tree[k].w=min(tree[k<<1].w,tree[k<<1|1].w); } void ask(int k) { if(tree[k].l>=a&&tree[k].r<=b) { minn=min(minn,tree[k].w); return ; } if(tree[k].f) down(k); int mid=(tree[k].r+tree[k].l)>>1; if(a<=mid) ask(k<<1); if(b>mid) ask(k<<1|1); } int main() { m=read(),n=read(),c=read(); build(1,1,n); for(int i=1;i<=m;i++) { node[i].x=read(),node[i].y=read(); node[i].z=read();node[i].y--; } sort(node+1,node+1+m,cmp); for(int i=1;i<=m;i++) { a=node[i].x,b=node[i].y; minn=0x7fffffff;ask(1); if(minn>node[i].z) x=-node[i].z,change(1),ans+=node[i].z; else x=-minn,change(1),ans+=minn; } printf("%lld",ans); }