由于是区间求和,因此我们在更新某个节点的时候,需要往上更新节点信息,也就有了tree[root].val=tree[L(root)].val+tree[R(root)].val;

但是我们为了把懒标记打上,当节点表示的区间是完全被询问区间包含,那么这个区间的信息都是有用的,因此我们其实只需要把这个节点更新,并打上懒标记即可。如果以后update 或者 query 需要跑到下面,直接往下pushdown即可。

pushdown的时候,由于当前层的信息已经更新,我们需要把信息往下推,并把子节点的信息维护,因此需要把laze标记往下打,并且往下更新修改即可

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
const int maxn = ;
long long sum;
inline int L(int r)
{
return r<<;
}
inline int R(int r)
{
return r<<|;
}
inline int MID(int l,int r)
{
return (l+r)>>;
}
struct node
{
int left,right;
long long val,add;
} tree[maxn<<];
long long b[maxn];
void pushdown(int root)
{
if (tree[root].add) //这个节点内部需要往下更新
{
tree[L(root)].add+=tree[root].add;//把laze标记往下传递 以后再进行更深的节点
tree[R(root)].add+=tree[root].add;
tree[L(root)].val+=(tree[L(root)].right-tree[L(root)].left+)*tree[root].add;//laze标记应该标记在自己的本身的位置 去改变下一个位置
tree[R(root)].val+=(tree[R(root)].right-tree[R(root)].left+)*tree[root].add;
tree[root].add=;//消除标记
}
}
void buildtree(int root,int l,int r)
{
tree[root].left=l;
tree[root].right=r;
tree[root].add=;
if(l==r)
{
tree[root].val=b[l];
return;
}
int mid=MID(l,r);
buildtree(L(root),l,mid);
buildtree(R(root),mid+,r);
tree[root].val=tree[L(root)].val+tree[R(root)].val;
}
void update(int root,int l,int r,long long v)
{
if(l<=tree[root].left && tree[root].right<=r)//包含在询问的区间内部
{
tree[root].add+=v;//打上标记
tree[root].val+=v*(tree[root].right-tree[root].left+);//修改
return;
}
pushdown(root);
if(tree[root].left==tree[root].right)
{
return;
}
int mid=MID(tree[root].left,tree[root].right);
if(l>mid)
update(R(root),l,r,v);//左区区间仅仅在右儿子节点中
else if (r<=mid)update(L(root),l,r,v);//仅仅在左儿子节点中
else
{
update(L(root),l,mid,v);//继续向下询问
update(R(root),mid+,r,v);//继续向下询问
}
tree[root].val=tree[L(root)].val+tree[R(root)].val;//把更新往上修改
}
void query(int root,int l,int r)
{
if (l<=tree[root].left && tree[root].right<=r)
{
sum+=tree[root].val;
return;
}
pushdown(root);
if(tree[root].left==tree[root].right)return;
int mid=MID(tree[root].left,tree[root].right);
if (l>mid)query(R(root),l,r);
else if (r<=mid)query(L(root),l,r);
else
{
query(L(root),l,mid);
query(R(root),mid+,r);
}
}
int main()
{
int n,m;
char op;
int tmp1,tmp2;
long long tmp3;
while(~scanf("%d%d",&n,&m))
{
for (int i=; i<=n; i++)
{
scanf("%lld",&b[i]);
}
buildtree(,,n);
while(m--)
{
scanf(" %c",&op);
if (op=='Q')
{
scanf("%d%d",&tmp1,&tmp2);
sum=;
query(,tmp1,tmp2);
printf("%lld\n",sum);
}
else
{
scanf("%d%d%lld",&tmp1,&tmp2,&tmp3);
update(,tmp1,tmp2,tmp3);
}
}
}
return ;
}

POJ - 3468 线段树区间修改,区间求和的更多相关文章

  1. poj 3468(线段树)

    http://poj.org/problem?id=3468 题意:给n个数字,从A1 …………An m次命令,Q是查询,查询a到b的区间和,c是更新,从a到b每个值都增加x.思路:这是一个很明显的线 ...

  2. POJ - 3468 线段树单点查询,单点修改区间查询,区间修改模板(求和)

    题意: 给定一个数字n,表示这段区间的总长度.然后输入n个数,然后输入q,然后输入a,b,表示查询a,b,区间和,或者输入c 再输入三个数字a,b,c,更改a,b区间为c 思路: 线段树首先就是递归建 ...

  3. C - A Simple Problem with Integers POJ - 3468 线段树模版(区间查询区间修改)

    参考qsc大佬的视频 太强惹 先膜一下 视频在b站 直接搜线段树即可 #include<cstdio> using namespace std; ; int n,a[maxn]; stru ...

  4. poj 3468 线段树 成段增减 区间求和

    题意:Q是询问区间和,C是在区间内每个节点加上一个值 Sample Input 10 51 2 3 4 5 6 7 8 9 10Q 4 4Q 1 10Q 2 4C 3 6 3Q 2 4Sample O ...

  5. POJ 3468 线段树区间修改查询(Java,c++实现)

    POJ 3468 (Java,c++实现) Java import java.io.*; import java.util.*; public class Main { static int n, m ...

  6. hdu 1698+poj 3468 (线段树 区间更新)

    http://acm.hdu.edu.cn/showproblem.php?pid=1698 这个题意翻译起来有点猥琐啊,还是和谐一点吧 和涂颜色差不多,区间初始都为1,然后操作都是将x到y改为z,注 ...

  7. HDU 2665.Kth number-可持久化线段树(无修改区间第K小)模板 (POJ 2104.K-th Number 、洛谷 P3834 【模板】可持久化线段树 1(主席树)只是输入格式不一样,其他几乎都一样的)

    Kth number Time Limit: 15000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total ...

  8. poj 3468 线段树区间更新/查询

    Description You have N integers, A1, A2, ... , AN. You need to deal with two kinds of operations. On ...

  9. POJ 3468 (线段树 区间增减) A Simple Problem with Integers

    这题WA了好久,一直以为是lld和I64d的问题,后来发现是自己的pushdown函数写错了,说到底还是因为自己对线段树理解得不好. 因为是懒惰标记,所以只有在区间分开的时候才会将标记往下传递.更新和 ...

  10. POJ 3468<线段树,区间add>

    题目连接 //位运算 k<<1 相当于 k*2 k<<1|1 相当于 k*2+1 /* 修改区间内的值,并且维护区间和. 详见代码 */ #include<cstdio& ...

随机推荐

  1. JAVA多线程的问题以及处理(二)【转】

    使用互斥解决多线程问题是一种简单有效的解决办法,但是由于该方法比较简单,所以只能解决一些基本的问题,对于复杂的问题就无法解决了. 解 决多线程问题的另外一种思路是同步.同步是另外一种解决问题的思路,结 ...

  2. onclick="return function()"的使用情况

    根据function的返回值,进行下一步操作,当返回值为true时,进行下一步操作,当返回值为false时,不进行操作. 例如:当在 <a href="url" onclic ...

  3. Oracle完全复制表结构的存储过程

    最近在处理一个分表的问题时,需要为程序创建一个自动分表的存储过程,需要保证所有表结构,约束,索引等等一致,此外视图,存储过程,权限等等问题暂不用考虑. 在Mysql中,创建分表的存储过程,相当简单:c ...

  4. Android 自定义ListView单击事件失效

    因为自带的listView不能满足项目需求,通过实现自己的Adapter去继承ArrayAdapter 来实现自定义ListView的Item项目. 出现点击ListView的每一项都不会执行setO ...

  5. Ubuntu 12.04上安装R语言

    Ubuntu 12.04上安装R语言 作者:凯鲁嘎吉 - 博客园 http://www.cnblogs.com/kailugaji/ R的安装 sudo gedit /etc/apt/sources. ...

  6. C语言 投票系统:给定候选人,从键盘输入候选人的名字,统计票数,并输出最终获胜者

    投票系统:给定候选人名单,从键盘输入候选人的名字,统计票数,并输出最终获胜者.若投票人输入的名字不在其候选名单上,则该票数无效. //凯鲁嘎吉 - 博客园 http://www.cnblogs.com ...

  7. [福大软工] Z班 第1次成绩排行榜

    作业地址 http://www.cnblogs.com/easteast/p/7403491.html 作业要求 (1)回想一下你初入大学时对计算机专业的畅想 当初你是如何做出选择计算机专业的决定的? ...

  8. Linux 简介(day1)

    一.Linux 诞生于1991年 二.创始人:林纳斯.托瓦茨(Linus Torvalds) 三.logo:企鹅 四.Linux完整系统包括 1.Linux kernel (Linux 内核) 2.f ...

  9. 从Hadoop到Spark的架构实践

    当下,Spark已经在国内得到了广泛的认可和支持:2014年,Spark Summit China在北京召开,场面火爆:同年,Spark Meetup在北京.上海.深圳和杭州四个城市举办,其中仅北京就 ...

  10. git 使用及常用命令介绍

    一.git 常用命令 git clone 地址 克隆项目 git status 查看当前状态 git add 文件或文件夹 (加入本地暂存目录) git commit -m "注释" ...