由于是区间求和,因此我们在更新某个节点的时候,需要往上更新节点信息,也就有了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. mcelog用法详解

    手动启动mcelog方法: # mcelog --daemon Run mcelog in daemon mode, waiting for errors from the kernel. 后台服务启 ...

  2. ASP.NET -- WebForm -- .aspx与.aspx.cs文件

    ASP.NET -- WebForm --  .aspx与.aspx.cs文件 1. ASP.NET -- WebForm(C#)文件 .aspx文件:是Html页面,页面的布局,样式在该文件中设计. ...

  3. C++借助curses库实现俄罗斯方块

    主要要实现如下几个功能:方块的移动控制.方块变形.判定方块是否接触边界和进行方块堆积.对方块进行消除. 1.方块的移动控制上下左右四个方向上-->变形,下-->加速下落,左-->向左 ...

  4. SD寄售-寄售补充

    SD寄售-寄售补充 概述: 寄售就是企业将货物寄放在客户处,或者在自己的仓库为客户保留库存,货物所有权归公司,当客户将库存消耗掉,才算公司的销售.公司才开票给客户. SAP SD寄售涉及4个业务过程, ...

  5. ionic app开发遇到的问题

    :processDebugResources FAILED FAILURE: Build failed with an exception. * What went wrong: Execution ...

  6. 洛谷P1904

    法一,数字太大,可能通过不了   #include <iostream>#include <algorithm>#include <cstdio>using nam ...

  7. C#深度学习の枚举类型(IEnumerator,IEnumerable)

    一.关于枚举的含义 .Net提供了可枚举类型的接口IEnumerable和枚举器接口IEnumerator,程序集System.Collections 另: IQueryable 继承自IEnumer ...

  8. 安装Anaconda 之后使用ubuntu自带python

    我们知道,Ubantu系统会自带python,当你在terminal窗口中输入python,就会显示默认安装的python的信息.比如我的16.04就自带了python2.7和3.5,但是安装了Ana ...

  9. LINUX 查看当前系统的内存使用情况 free

    每天学习一点点 编程PDF电子书.视频教程免费下载:http://www.shitanlife.com/code # free 显示结果如下: Mem:表示物理内存统计 total 内存总数 8057 ...

  10. mysql 使用正则表达式查询

    SELECT * FROM `qq` where qq_name!='no' and qq_gender='女' and qq_location!='no' and qq_location!='' a ...