poj 3468 线段树(区间更新)模板题

来源:互联网 发布:爱古筝软件 编辑:程序博客网 时间:2024/04/29 02:45

题目链接  点击打开链接


以下为参考链接

点击打开链接

点击打开链接


线段树单点更新和区间更新的区别:

1.每个结点中多了一个add值,代表该结点以下的结点需要增加的值;

2.build函数中,如果在建树的过程中就赋值给num,那么在建完树之后不要忘记pushup,因为此时只是叶子结点有值,上面的值都为空;这个在区间更新中很常用,因为区间更新中如果输入一个值,然后更新一个值,这样会很麻烦,会耗费更多的时间;

3.update函数中,区间更新多了一个pushdown函数,并且更新sum和add值的判断条件是树中结点的l~r和要更新的区间的l~r相等,此时sum加的值是整个区间的长度*要更新的值,然后add值记录后面每个结点需要加上的值,即:c;

4.pushdown函数最后不要忘了将延时标记add清零;

#include <iostream>#include <cstring>#include <algorithm>#include <vector>#include <cstdio>#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1  using namespace std;const int inf=1<<20;const int M = 1e5+5;long long sum[M<<2],add[M<<2];//重点 lazy标记:add[rt] 代表 rt以下的节点所要增加的值 struct node{int l,r;int mid(){return (l+r)>>1;}}tree[M<<2];void pushup(int rt){sum[rt]=sum[rt<<1]+sum[rt<<1|1];}void build(int l,int r,int rt){tree[rt].l=l;tree[rt].r=r;add[rt]=0;//if(l==r)//leaf{scanf("%I64d",&sum[rt]);return;}int m=tree[rt].mid();build(lson);build(rson);pushup(rt);}void PushDown(int rt,int len)//区间rt的长度为len {if(add[rt]){add[rt<<1]+=add[rt];add[rt<<1|1]+=add[rt];//往下标记 sum[rt<<1]+=add[rt]*(len-(len/2));sum[rt<<1|1]+=add[rt]*(len/2);add[rt]=0;//更新后还原add[rt] }}void update(int c,int l,int r,int rt) // 区间l,r中的每个元素增加c {if(tree[rt].l==l&&tree[rt].r==r) //lazy思想 { add[rt]+=c; sum[rt]+=c*(r-l+1); return;//暂时不更新子节点的值 //在某部分update操作的时候需要用到那部分没有更新的节点的值的时候, //这里可能有点绕口。这时就掉用PushDown()函数更新子节点的数值。 }if(tree[rt].l==tree[rt].r)return;PushDown(rt,tree[rt].r-tree[rt].l+1);// 要分解区间时(要用到子区间) //更新子区间(把以前还没更新的更新了) int m=tree[rt].mid();//更新查询要区间l,r所在的那一段  if(r<=m)//在该节点的左边 {update(c,l,r,rt<<1);}else if(l>m){update(c,l,r,rt<<1|1);}else//横跨中点 继续分解 {update(c,l,m,rt<<1);update(c,m+1,r,rt<<1|1);}pushup(rt);}long long query(int l,int r,int rt){if(l==tree[rt].l&&r==tree[rt].r)//完全包含 {return sum[rt];}//要用到子区间PushDown(rt,tree[rt].r-tree[rt].l+1);int m=tree[rt].mid();long long res=0;//分解区间 if(r<=m) {res+=query(l,r,rt<<1); }  else if(l>m)//所查询区间在右半段  { res+=query(l,r,rt<<1|1); } else//l<m<r<tree[rt].r { res+=query(l,m,rt<<1); res+=query(m+1,r,rt<<1|1); } return res;}int main(){int n,q;cin>>n>>q;build(1,n,1);while(q--){char c;cin>>c;if(c=='C'){int a,b,c;cin>>a>>b>>c;update(c,a,b,1);}if(c=='Q'){int l,r;cin>>l>>r;cout<<query(l,r,1)<<endl;} }return 0;}



0 0
原创粉丝点击