[线段树](模板题)线段树1(或称线段树:加法)
2018-03-12 21:15
204 查看
题目描述
如题,已知一个数列,你需要进行下面两种操作:
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
说明
数据规模:
对于30%的数据:N<=8,M<=10
对于70%的数据:N<=1000,M<=10000
对于100%的数据:N<=100000,M<=100000
(数据保证在int64/long long数据范围内)
分析
线段树第一题,我他妈的这什么鬼题啊怀着兴奋的心情开始写这篇题解
然后
这个
线段树
题解
就完了
嗯
对
的确是这样的
好吧
我
线段树
打钱
这个
我觉得
最难点
就是
那个
叫做
什么
懒惰标记
哦不对
是延迟标记
嗯
就是这个东西
没错
如题,已知一个数列,你需要进行下面两种操作:
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
说明
数据规模:
对于30%的数据:N<=8,M<=10
对于70%的数据:N<=1000,M<=10000
对于100%的数据:N<=100000,M<=100000
(数据保证在int64/long long数据范围内)
分析
线段树第一题,我他妈的这什么鬼题啊怀着兴奋的心情开始写这篇题解
然后
这个
线段树
题解
就完了
嗯
对
的确是这样的
好吧
我
线段树
打钱
这个
我觉得
最难点
就是
那个
叫做
什么
懒惰标记
哦不对
是延迟标记
嗯
就是这个东西
没错
#include <iostream> #include <cstdio> #define l(p) tree[p].l #define r(p) tree[p].r #define sum(p) tree[p].sum #define poi(p) tree[p].poi #define rep(i,a,b) for (i=a;i<=b;i++) struct ST { int l,r; long long sum,poi; }tree[404040]; int n,m; int c,l,r,x; long long d; int i; long long a[101010]; void build(int p,int l,int r) { l(p)=l;r(p)=r; if (l==r) {sum(p)=a[l];return;} int mid=(l+r)/2; if (l<=mid) build(p*2,l,mid); if (r>mid) build(p*2+1,mid+1,r); sum(p)=sum(p*2)+sum(p*2+1); } void spread(int p) { if (poi(p)) { sum(p*2)+=(r(p*2)-l(p*2)+1)*poi(p); sum(p*2+1)+=(r(p*2+1)-l(p*2+1)+1)*poi(p); poi(p*2)+=poi(p); poi(p*2+1)+=poi(p); poi(p)=0; } } void change(int p,int l,int r,long long d) { if (l<=l(p)&&r(p)<=r) { sum(p)+=(r(p)-l(p)+1)*d; poi(p)+=d; return; } spread(p); int mid=(l(p)+r(p))/2; if (l<=mid) change(p*2,l,r,d); if (r>mid) change(p*2+1,l,r,d); sum(p)=sum(p*2)+sum(p*2+1); } long long ask(int p,int l,int r) { if (l>r(p)||r<l(p)) return 0; if (l<=l(p)&&r(p)<=r) return sum(p); spread(p); int mid=(l(p)+r(p))/2; long long val=0; if (l<=mid) val+=ask(p*2,l,r); if (r>mid) val+=ask(p*2+1,l,r); return val; } int main() { scanf("%d%d",&n,&m); rep(i,1,n) scanf("%lld",&a[i]); build(1,1,n); rep(i,1,m) { scanf("%d%d%d",&c,&l,&r); if (c==1) { scanf("%lld",&d); change(1,l,r,d); } else printf("%lld\n",ask(1,l,r)); } }
相关文章推荐
- 线段树(加法和乘法的模板)
- 算法模板——线段树1(区间加法+区间求和)
- 洛谷P3373 [ 模板] 线段树 (乘法和加法)
- 算法模板——线段树6(二维线段树:区域加法+区域求和)(求助phile)
- 【模板】可持久化线段树(主席树)
- 线段树模板
- 线段树,小模板
- RMQ 线段树实现+DP实现 模板
- 刘汝佳大数模板(只含加法)
- 2017 icpc 南宁赛区 F.Overlapping Rectangles(重叠矩形的最大面积+线段树模板)
- 【整合】树链剖分模板(线段树维护)
- 大数加法模板
- 线段树模板
- 线段树模板及习题
- cd 915E(离散化+线段树)(新线段树模板)
- Luck and Love(二维线段树单点更新+区间查询+模板)
- 洛谷 3372_【模板】线段树 1_线段树
- 【模板】线段树_区间最值、区间求和、修改
- 线段树(递归)模板
- 线段树的代码模板