【洛谷P3372】【模板】线段树 1
来源:互联网 发布:手机淘宝电脑版在哪里 编辑:程序博客网 时间:2024/06/05 15:05
题目描述
如题,已知一个数列,你需要进行下面两种操作:
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的结果。
输入输出样例
输入样例#1:
5 5
1 5 4 2 3
2 2 4
1 2 3 2
2 3 4
1 1 5 1
2 1 4
输出样例#1:
11
8
20
说明
时空限制:1000ms,128M
数据规模:
对于30%的数据:N<=8,M<=10
对于70%的数据:N<=1000,M<=10000
对于100%的数据:N<=100000,M<=100000
(数据已经过加强^_^,保证在int64/long long数据范围内)
样例说明:
题解
沉迷线段树无法自拔
记下这个代码,以后省选会用
总体思想就是维护两个线段树,一个存对应区间每一个数加的值,一个存对应区间每一个数的和(不包括区间每一个数都要加的值)
更新时如果要加区间全部包含当前区间则第一个线段树对应区间+=x
否则第二个线段树+=(min(b,r)-max(a,l))*x,之后递归。
具体实现见下(PS:一定要用long long)
My Code
(调试代码感人)
#include<iostream>#include<cstring>#include<cstdio>#include<algorithm>#include<cmath>using namespace std;typedef long long ll;ll dt[2000005],dtb[2000005];int n,m;ll itmp[500005];void init(int k,int l,int r) { if(r-l==1) { dtb[k]=itmp[l]; //printf("%d %d\n",l,r); } else { //printf("%d %d\n",l,r); int chl=k*2,chr=k*2+1; init(chl,l,(l+r)/2); init(chr,(l+r)/2,r); dtb[k]=dtb[chl]+dtb[chr]; //printf("%d %d %d %d\n",dt[k],l,(l+r)/2,r); }}void add(int a,int b,ll x,int k,int l,int r) { if(a<=l&&r<=b){ dt[k]+=x; }else if(l<b&&a<r){ dtb[k]+=((ll)min(b,r)-(ll)max(a,l))*x; int chl=k*2,chr=k*2+1;// printf("%d %d\n",l,r);gouliguojiashengsiyi,qiyinhuofubiquzhi add(a,b,x,chl,l,(l+r)/2); add(a,b,x,chr,(l+r)/2,r); } }ll query(int a,int b,int k,int l,int r) { if(b<=l||r<=a)return 0; if(a<=l&&r<=b) { //printf("%d %d\n",k,dt[k]); return dt[k]*(ll)(r-l)+dtb[k]; } if(r-l!=1){ int chl=k*2,chr=k*2+1; ll res=dt[k]*((ll)min(b,r)-(ll)max(a,l)); res+=query(a,b,chl,l,(l+r)/2); res+=query(a,b,chr,(l+r)/2,r); //printf("%d %d %d %d\n",res,l,(l+r)/2,r); return res; }}int main() { memset(dt,0,sizeof(dt)); memset(dtb,0,sizeof(dtb)); memset(itmp,0,sizeof(itmp)); scanf("%d%d",&n,&m); for(int i=1; i<=n; i++) { scanf( "%lld",&itmp[i]); } init(1,1,n+1); int tp,x,y; for(int i=1;i<=m;i++) { scanf("%d%d",&tp,&x); if(tp==2) { printf("%lld\n",query(x,x+1,1,1,n+1)); } if(tp==1) { ll z; scanf("%d%lld",&y,&z); add(x,y+1,z,1,1,n+1); } } return 0;}
0 0
- 【洛谷P3372】【模板】线段树 1
- 洛谷 P3372【模板】线段树 1
- 洛谷P3372 【模板】线段树 1
- 洛谷 P3372 【模板】线段树 1
- 【洛谷P3372】【模板】线段树1
- 洛谷 P3372 线段树模板
- [P3372][模板]线段树1
- 【洛谷】P3372线段树1 线段树模板
- 洛谷P3372线段树模板1(改段求段)
- 洛谷P3372 【模板】线段树 1(lazy)
- 【模板】树状数组 区间修改,区间求和 (模板题:洛谷P3372线段树1)
- 洛谷p3372 线段树模版
- Luogu-P3372 (Lazy_tag 线段树模板)
- 【模板】线段树 区间加,区间求和 (模板题:P3372线段树1)
- 洛谷 P3372 线段树 1(树状数组做法)
- 关于 线段树 下传(AC) 不做标记 下传(T3)模板洛谷p3372
- 【模板】线段树 1
- 线段树模板1
- 练习
- 引用传递
- 第三方库-Picasso
- 我所理解的设计模式——对象行为之命令(Comand)模式
- Java容易忽略的几个知识点!!!
- 【洛谷P3372】【模板】线段树 1
- POJ 3211 Washing Clothes(01背包)@
- SSH 小技巧大全
- AndroidStudio的使用技巧
- 详解原型链继承
- Java中无返回值的return语句使用总结
- 自考、起航!
- Leetcode #8 String to Integer (atoi)
- volatile关键字浅析