洛谷 P3372 【模板】线段树 1(线段树区间加区间找)
题目描述
如题,已知一个数列,你需要进行下面两种操作:
1.将某区间每一个数加上x
2.求出某区间每一个数的和
输入格式
第一行包含两个整数N、M,分别表示该数列数字的个数和操作的总个数。
第二行包含N个用空格分隔的整数,其中第i个数字表示数列第i项的初始值。
接下来M行每行包含3或4个整数,表示一个操作,具体如下:
操作1: 格式:1 x y k 含义:将区间[x,y]内每个数加上k
操作2: 格式:2 x y 含义:输出区间[x,y]内每个数的和
输出格式
输出包含若干行整数,即为所有操作2的结果。
输入输出样例
5 5 1 5 4 2 3 2 2 4 1 2 3 2 2 3 4 1 1 5 1 2 1 4
11 8 20
说明/提示
时空限制:1000ms,128M
数据规模:
对于30%的数据:N<=8,M<=10
对于70%的数据:N<=1000,M<=10000
对于100%的数据:N<=100000,M<=100000
(数据已经过加强^_^,保证在int64/long long数据范围内)
样例说明:
#include <cstdio> #include <iostream> #include <cmath> #include <string> #include <cstring> #include <algorithm> #include <queue> #include <vector> #include <map> using namespace std;#define ll long long #define eps 1e-9const int inf = 0x3f3f3f3f; const int mod = 1e9+7;ll n, m, a[1000000+8], ans;struct node {ll left, right, sum, lz; }tree[1000000+8];void build(ll left, ll right, ll i)///建树 {tree[i].lz = 0;///懒惰标记初始化为0tree[i].left = left;tree[i].right = right;if(left == right)///如果已经是叶子结点 {tree[i].sum = a[left];return ;}ll mid = (right+left)/2;build(left, mid, i*2);///往左边的区间进行建树build(mid+1, right, i*2+1);///往右边的区间进行建树tree[i].sum = tree[i*2].sum+tree[i*2+1].sum;///自己的和等于左儿子和右儿子的和 }void push_down(ll i)///把自己的lazytage归零,并给自己的儿子加上,并让自己的儿子加上k*(r-l+1) {if(tree[i].lz != 0)///如果这个点已经被标记了 {tree[i*2].lz += tree[i].lz;///左儿子的懒惰标记等于父亲的懒惰标记tree[i*2+1].lz += tree[i].lz;///右儿子的懒惰标记等于父亲的懒惰标记ll mid = (tree[i].left+tree[i].right)/2;tree[i*2].sum += tree[i].lz*(mid-tree[i*2].left +1);///左儿子的和等于它所控制的区间的和tree[i*2+1].sum += tree[i].lz*(tree[i*2+1].right-mid);///右儿子的和等于它所控制的区间的和tree[i].lz = 0;///父节点懒惰标记归零 }return ; }void pls(ll i, ll l, ll r, ll k)///区间加 {if(tree[i].right <= r && tree[i].left >= l)///如果这个区间就在目标区间的内部 {tree[i].sum += k*(tree[i].right-tree[i].left+1);///这个区间的和 等于(这个区间原本的和)+(k*这个区间的元素个数)tree[i].lz += k;///懒惰标记,表示它已经加了kreturn ;}push_down(i);///把自己的lazytage归零,并给自己的儿子加上,并让自己的儿子加上k*(r-l+1)if(tree[i*2].right >= l)///如果这个区间与左边部分区间重叠,就往左边区间每个元素加上kpls(i*2, l, r, k);if(tree[i*2+1].left <= r)///如果这个区间与右边部分区间重叠,就往右边区间每个元素加上kpls(i*2+1, l, r, k);tree[i].sum = tree[i*2].sum+tree[i*2+1].sum;///父节点的和等于左儿子的和加右儿子的和return ; }void search(ll i, ll l, ll r)///查找区间和 {if(tree[i].left >= l && tree[i].right <= r)///如果这个区间就在目标区间的内部 {ans += tree[i].sum;return ;}if(tree[i].lz)push_down(i);///一层一层的进行标记,方便后来的查找区间和ll mid = (tree[i].left+tree[i].right)/2;if(l <= mid)///如果这个区间与左边部分区间重叠,就 ans + 左边区间每个元素加上ksearch(i*2, l, r);if(mid<r)///如果这个区间与右边部分区间重叠,就 ans + 右边区间每个元素加上ksearch(i*2+1, l, r); }int main() {scanf("%lld%lld", &n, &m);for(ll i = 1; i <= n; i++)scanf("%lld", &a[i]);build(1, n, 1);///初始化线段树for(ll i = 1; i <= m; i++){ll f;scanf("%lld", &f);if(f == 1){ll x, y, z;scanf("%lld%lld%lld", &x, &y, &z);pls(1, x, y, z);///从根节点开始进行区间加c }else if(f == 2){ll x, y;scanf("%lld%lld", &x, &y);ans = 0;search(1, x, y);printf("%lld\n", ans);///输出区间[a, b]的值 }}return 0; }
转载于:https://www.cnblogs.com/RootVount/p/11285251.html
洛谷 P3372 【模板】线段树 1(线段树区间加区间找)相关推荐
- 线段树动态开点区间加区间求和
线段树动态开点区间加区间求和 题目来源: 陕西师范大学第七届程序设计竞赛网络同步赛 H. 万恶的柯怡 思想: 保证叶子节点被完整的覆盖,需要开节点,就把左右儿子都开出来,其余和普通线段树一样. tip ...
- 洛谷 p3372 模板-线段树 1
题目描述 如题,已知一个数列,你需要进行下面两种操作: 1.将某区间每一个数加上x 2.求出某区间每一个数的和 输入输出格式 输入格式: 第一行包含两个整数N.M,分别表示该数列数字的个数和操作的总个 ...
- 洛谷 - P1886 滑动窗口(单调队列/线段树)
题目链接:点击查看 题目大意:给出一个由n个数构成的序列,再给出一个长度为k的窗口,这个窗口从第一个下标开始一直向后移动,每次移动一个单位,每次移动询问一次该窗口中的最大值和最小值,最后输出答案 题目 ...
- 【题解】洛谷P4145 花神游历各国(线段树)
洛谷P4145:https://www.luogu.org/problemnew/show/P4145 思路 这道题的重点在于sqrt(1)=1 一个限制条件 与正常线段树不同的是区间修改为开方 那么 ...
- 专题·树链剖分【including 洛谷·【模板】树链剖分
初见安~~~终于学会了树剖~~~ [兴奋]当初机房的大佬在学树剖的时候我反复强调过:"学树剖没有前途的!!!" 恩.真香. 一.重链与重儿子 所谓树剖--树链剖分,就是赋予一个链的 ...
- 洛谷·【模板】点分树 | 震波【including 点分树
初见安-这里是传送门:洛谷P6329 [模板]点分树 | 震波 一.点分树 其实你会点分治的话,点分树就是把点分治时的重心提出来重新连城一棵树. 比如当前点是u,求出子树v的重心root后将root与 ...
- ⌈洛谷1505⌋⌈BZOJ2157⌋⌈国家集训队⌋旅游【树链剖分】
题目链接 [洛谷] [BZOJ] 题目描述 Ray 乐忠于旅游,这次他来到了T 城.T 城是一个水上城市,一共有 N 个景点,有些景点之间会用一座桥连接.为了方便游客到达每个景点但又为了节约成本,T ...
- 【JZOJ3794】【洛谷P1383】高级打字机【主席树】
题目大意: 题目链接: 洛谷:https://www.luogu.org/problemnew/show/P1383 JZOJ:https://jzoj.net/senior/#main/show/3 ...
- 洛谷 P3372 【模板】线段树 1
文章目录 题目描述 输入格式 输出格式 输入输出样例 说明 [样例解释] AC的C++代码(结合注释理解) 题目描述 如题,已知一个数列,你需要进行下面两种操作: 将某区间每一个数加上k. 求出某区间 ...
最新文章
- sed 格式化输出df -h
- 新建swap分区的规划、挂载和自动挂载示例
- shell 获取 mysql 行数_一个Shell小脚本精准统计Mysql每张表的行数实现
- P4 前端编译器p4c-bm、后端编译器bmv2命令安装 make error问题
- 【渝粤教育】电大中专会计电算化 (2)作业 题库
- Linux异步IO实现方案总结
- Trick(四)——翻转字符串的实现
- 真·不怪云原生:探寻IT大厂逐渐云化的秘密!
- Debian9用户态下安装pipenv
- 系统架构设计-计算机组成与体系结构
- 64位plsql和64位Oracle客户端安装以及注册,内含百度云资源
- 编写一个以C 语言为基础的DSP程序
- ENVI剪裁图片( 剪裁、裁移位等问题)
- 微信朋友圈 腾讯服务器,朋友圈@微信能得一面红旗?腾讯服务器一度宕机
- 高等数学——驻点,拐点,极值点
- 在日冕病毒时代的爱情-远程工作的技巧,窍门和最佳实践
- 如何申请屏蔽垃圾短信
- 一步一步构建手机WebApp开发——页面布局篇
- DSP技术是利用计算机或,DSP技术综述1
- 2020中北大学计算机调剂名额,2020年中北大学考研调剂安排