线段树练习 3&P3372 【模板】线段树 1
给你N个数,有两种操作:
1:给区间[a,b]的所有数增加X
2:询问区间[a,b]的数的和。
第一行一个正整数n,接下来n行n个整数,
再接下来一个正整数Q,每行表示操作的个数,
如果第一个数是1,后接3个正整数,
表示在区间[a,b]内每个数增加X,如果是2,
表示操作2询问区间[a,b]的和是多少。
pascal选手请不要使用readln读入
对于每个询问输出一行一个答案
3
1
2
3
2
1 2 3 2
2 2 3
9
数据范围
1<=n<=200000
1<=q<=200000
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------
题目描述
如题,已知一个数列,你需要进行下面两种操作:
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数据范围内)
样例说明:
代码实现:
线段树练习 3:
1 #include<cstdio> 2 #include<iostream> 3 #define LL long long 4 using namespace std; 5 LL n,m,a,b,c,d; 6 struct nate{LL l,r,s,flag;}t[800000]; 7 void heritage(LL k){//标记传递。当使用某一区间时,把它的标记下传,并更改左右儿子的需求值。 8 LL lson=k*2,rson=k*2+1; 9 t[lson].flag+=t[k].flag; 10 t[lson].s+=(t[lson].r-t[lson].l+1)*t[k].flag; 11 t[rson].flag+=t[k].flag; 12 t[rson].s+=(t[rson].r-t[rson].l+1)*t[k].flag; 13 t[k].flag=0; 14 } 15 void make_tree(LL k,LL l,LL r){ 16 LL lson=k*2,rson=k*2+1; 17 t[k].l=l;t[k].r=r; 18 if(l==r){ 19 scanf("%lld",&t[k].s); 20 return; 21 } 22 LL mid=(l+r)/2; 23 make_tree(lson,l,mid); 24 make_tree(rson,mid+1,r); 25 t[k].s=t[lson].s+t[rson].s; 26 } 27 void interval_change(LL k,LL l,LL r,LL v){ 28 LL lson=k*2,rson=k*2+1; 29 if(t[k].l==l&&t[k].r==r){ 30 t[k].flag+=v; 31 t[k].s+=(t[k].r-t[k].l+1)*v; 32 return; 33 } 34 if(t[k].flag) heritage(k); 35 LL mid=(t[k].l+t[k].r)/2; 36 if(l<=mid) interval_change(lson,l,min(r,mid),v); 37 if(r>mid) interval_change(rson,max(l,mid+1),r,v); 38 t[k].s=t[lson].s+t[rson].s; 39 } 40 LL interval_query(LL k,LL l,LL r){ 41 LL lson=k*2,rson=k*2+1; 42 if(t[k].l==l&&t[k].r==r) return t[k].s; 43 if(t[k].flag) heritage(k); 44 long long mid=(t[k].l+t[k].r)/2,ans=0; 45 if(l<=mid) ans+=interval_query(lson,l,min(r,mid)); 46 if(r>mid) ans+=interval_query(rson,max(l,mid+1),r); 47 return ans; 48 } 49 int main(){ 50 scanf("%lld",&n); 51 make_tree(1,1,n); 52 scanf("%lld",&m); 53 for(int i=1;i<=m;i++){ 54 scanf("%lld",&a); 55 if(a==1){ 56 scanf("%lld%lld%lld",&b,&c,&d); 57 interval_change(1,b,c,d); 58 } 59 if(a==2){ 60 scanf("%lld%lld",&b,&c); 61 printf("%lld\n",interval_query(1,b,c)); 62 } 63 } 64 return 0; 65 }
【模板】线段树 1:
1 #include<cstdio> 2 #include<iostream> 3 using namespace std; 4 long long n,m,a,b,c,d; 5 struct nate{long long l,r,s,flag;}t[800000]; 6 void heritage(long long k){ 7 long long lson=k*2,rson=k*2+1; 8 t[lson].flag+=t[k].flag; 9 t[lson].s+=(t[lson].r-t[lson].l+1)*t[k].flag; 10 t[rson].flag+=t[k].flag; 11 t[rson].s+=(t[rson].r-t[rson].l+1)*t[k].flag; 12 t[k].flag=0; 13 } 14 void make_tree(long long k,long long l,long long r){ 15 long long lson=k*2,rson=k*2+1; 16 t[k].l=l;t[k].r=r; 17 if(l==r){ 18 scanf("%lld",&t[k].s); 19 return; 20 } 21 long long mid=(l+r)/2; 22 make_tree(lson,l,mid); 23 make_tree(rson,mid+1,r); 24 t[k].s=t[lson].s+t[rson].s; 25 } 26 void interval_change(long long k,long long l,long long r,long long v){ 27 long long lson=k*2,rson=k*2+1; 28 if(t[k].l==l&&t[k].r==r){ 29 t[k].flag+=v; 30 t[k].s+=(t[k].r-t[k].l+1)*v; 31 return; 32 } 33 if(t[k].flag) heritage(k); 34 long long mid=(t[k].l+t[k].r)/2; 35 if(l<=mid) interval_change(lson,l,min(r,mid),v); 36 if(r>mid) interval_change(rson,max(l,mid+1),r,v); 37 t[k].s=t[lson].s+t[rson].s; 38 } 39 long long interval_query(long long k,long long l,long long r){ 40 int lson=k*2,rson=k*2+1; 41 if(t[k].l==l&&t[k].r==r) return t[k].s; 42 if(t[k].flag) heritage(k); 43 long long mid=(t[k].l+t[k].r)/2,ans=0; 44 if(l<=mid) ans+=interval_query(lson,l,min(r,mid)); 45 if(r>mid) ans+=interval_query(rson,max(l,mid+1),r); 46 return ans; 47 } 48 int main(){ 49 scanf("%lld%lld",&n,&m); 50 make_tree(1,1,n); 51 for(int i=1;i<=m;i++){ 52 scanf("%lld",&a); 53 if(a==1){ 54 scanf("%lld%lld%lld",&b,&c,&d); 55 interval_change(1,b,c,d); 56 } 57 if(a==2){ 58 scanf("%lld%lld",&b,&c); 59 printf("%lld\n",interval_query(1,b,c)); 60 } 61 } 62 return 0; 63 }
其实两个题几乎一样,也是因为这个“几乎”,我洛谷上得了遍零分。
题目来源:CODE[VS],洛谷