首页 > 其他 > 详细

线段树练习 3&&P3372 【模板】线段树 1

时间:2017-01-16 22:23:43      阅读:200      评论:0      收藏:0      [点我收藏+]

给你N个数,有两种操作:

1:给区间[a,b]的所有数增加X

2:询问区间[a,b]的数的和。

输入描述 Input Description

第一行一个正整数n,接下来n行n个整数,

再接下来一个正整数Q,每行表示操作的个数,

如果第一个数是1,后接3个正整数,

表示在区间[a,b]内每个数增加X,如果是2,

表示操作2询问区间[a,b]的和是多少。

pascal选手请不要使用readln读入

输出描述 Output Description

对于每个询问输出一行一个答案

样例输入 Sample Input

3

1

2

3

2

1 2 3 2

2 2 3

样例输出 Sample Output

9

数据范围及提示 Data Size & Hint

数据范围

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的结果。

输入输出样例

输入样例#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数据范围内)

样例说明:

技术分享

代码实现:

线段树练习 3:

 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",&n);
50     make_tree(1,1,n);
51     scanf("%lld",&m);
52     for(int i=1;i<=m;i++){
53         scanf("%lld",&a);
54         if(a==1){
55             scanf("%lld%lld%lld",&b,&c,&d);
56             interval_change(1,b,c,d);
57         }
58         if(a==2){
59             scanf("%lld%lld",&b,&c);
60             printf("%lld\n",interval_query(1,b,c));
61         }
62     }
63     return 0;
64 }

【模板】线段树 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 }
View Code

其实两个题几乎一样,也是因为这个“几乎”,我洛谷上得了遍零分。

线段树练习 3&&P3372 【模板】线段树 1

原文:http://www.cnblogs.com/J-william/p/6291065.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!