1082 线段树练习 3

1082 线段树练习 3

时间限制: 3 s

空间限制: 128000 KB

题目等级 : 大师 Master

题目描述 Description

给你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 #include<cstdio>
 2 #define lson l,m,rt << 1
 3 #define rson m+1,r,rt<<1|1
 4 #define ll long long
 5
 6 const int N = 200010;
 7
 8 ll sum[N<<2];
 9 ll add[N<<2];
10 int n,q;
11
12 void pushup(int rt)
13 {
14     sum[rt] = sum[rt<<1] + sum[rt<<1|1];
15 }
16 void pushdown(int rt,int m)  //m长度,rt线段
17 {
18     if(add[rt])
19     {
20         add[rt<<1] += add[rt] ;
21         add[rt<<1|1] += add[rt];
22         sum[rt<<1] += add[rt] * (m - (m>>1));
23         sum[rt<<1|1] += add[rt] * (m>>1);
24         add[rt] = 0;
25     }
26 }
27 void build(int l,int r,int rt)
28 {
29     add[rt] = 0;
30     if(l==r)
31     {
32         scanf("%d",&sum[rt]);
33         return ;
34     }
35     int m = (l+r)>>1;
36     build(lson);
37     build(rson);
38     pushup(rt);
39 }
40 void update(int L,int R,int c,int l,int r,int rt)
41 {
42     if(L<=l && r<=R)
43     {
44         add[rt] += c;
45         sum[rt] += (ll)c * (r-l+1);
46         return ;
47     }
48     pushdown(rt,r-l+1);
49     int m = (l+r)>>1;
50     if(L<=m) update(L,R,c,lson);
51     if(m<R) update(L,R,c,rson);
52     pushup(rt);
53 }
54 ll query(int L,int R,int l,int r,int rt)
55 {
56     if(L<=l && r<=R)
57     {
58         return sum[rt];
59     }
60     pushdown(rt,r-l+1);
61     ll ret=0;
62     int m = (l+r)>>1;
63     if(L<=m) ret += query(L,R,lson);
64     if(m<R) ret += query(L,R,rson);
65     return ret;
66 }
67 int main()
68 {
69     scanf("%d",&n);
70     build(1,n,1);
71     scanf("%d",&q);
72     while(q--)
73     {
74         int a,b,c,x;
75         scanf("%d",&x);
76         if(x==1)
77         {
78             scanf("%d%d%d",&a,&b,&c);
79             update(a,b,c,1,n,1);
80         }
81         else
82         {
83             scanf("%d%d",&a,&b);
84             printf("%lld\n",query(a,b,1,n,1));
85         }
86     }
87     return 0;
88 }
时间: 2024-10-13 02:21:56

1082 线段树练习 3的相关文章

codevs 1082 线段树练习3

1082 线段树练习 3 时间限制: 3 s 空间限制: 128000 KB 题目等级 : 大师 Master 题目描述 Description 给你N个数,有两种操作: 1:给区间[a,b]的所有数增加X 2:询问区间[a,b]的数的和. 输入描述 Input Description 第一行一个正整数n,接下来n行n个整数, 再接下来一个正整数Q,每行表示操作的个数, 如果第一个数是1,后接3个正整数, 表示在区间[a,b]内每个数增加X,如果是2, 表示操作2询问区间[a,b]的和是多少.

codevs 1082 线段树联系3

1082 线段树练习 3 时间限制: 3 s 空间限制: 128000 KB 题目等级 : 大师 Master 题解 题目描述 Description 给你N个数,有两种操作: 1:给区间[a,b]的所有数增加X 2:询问区间[a,b]的数的和. 输入描述 Input Description 第一行一个正整数n,接下来n行n个整数, 再接下来一个正整数Q,每行表示操作的个数, 如果第一个数是1,后接3个正整数, 表示在区间[a,b]内每个数增加X,如果是2, 表示操作2询问区间[a,b]的和是多

codevs 1082 线段树练习 3

1082 线段树练习 3 时间限制: 3 s 空间限制: 128000 KB 题目等级 : 大师 Master 题目描述 Description 给你N个数,有两种操作: 1:给区间[a,b]的所有数增加X 2:询问区间[a,b]的数的和. 输入描述 Input Description 第一行一个正整数n,接下来n行n个整数, 再接下来一个正整数Q,每行表示操作的个数, 如果第一个数是1,后接3个正整数, 表示在区间[a,b]内每个数增加X,如果是2, 表示操作2询问区间[a,b]的和是多少.

Wikioi 1082线段树成段更新成段查询

这题从昨晚搞到现在敲了又改好久,刚开始是update中错了,然后找到了.但是还错,然后因为题目没有数据的范围提示,所以弄了好久都不知道哪错了,最后看评论才知道是超int了,改了之后还有错,然后才发现虽然改成long long了,但是输出的时候没改,哈哈-- #include <iostream> #include <cstdio> #include <algorithm> #include <cmath> #include <deque> #in

【树状数组区间修改区间求和】codevs 1082 线段树练习 3

http://codevs.cn/problem/1082/ [AC] 1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int maxn=2e5+2; 5 int n; 6 ll a[maxn]; 7 ll c1[maxn]; 8 ll c2[maxn]; 9 int lowbit(int x) 10 { 11 return x&-x; 12 } 13 void add(l

codevs 1082 线段树练习 3 --分块练习

时间限制: 3 s 空间限制: 128000 KB 题目等级 : 大师 Master 题目描述 Description 给你N个数,有两种操作: 1:给区间[a,b]的所有数增加X 2:询问区间[a,b]的数的和. 输入描述 Input Description 第一行一个正整数n,接下来n行n个整数, 再接下来一个正整数Q,每行表示操作的个数, 如果第一个数是1,后接3个正整数, 表示在区间[a,b]内每个数增加X,如果是2, 表示操作2询问区间[a,b]的和是多少. pascal选手请不要使用

codevs 1082 线段树练习 3 区间更新+延迟标记

题目描述 Description 给你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 对于每个询问输出一行

【codevs】1082 线段树练习 3

题目连接   http://codevs.cn/problem/1082/ Description 给你N个数,有两种操作: 1:给区间[a,b]的所有数增加X 2:询问区间[a,b]的数的和. Input 第一行一个正整数n,接下来n行n个整数, 再接下来一个正整数Q,每行表示操作的个数, 如果第一个数是1,后接3个正整数, 表示在区间[a,b]内每个数增加X,如果是2, 表示操作2询问区间[a,b]的和是多少. 输出描述 Output Description 对于每个询问输出一行一个答案 S

codevs 1082 线段树练习3 模板题

1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 long long a[2000003],sum[10000003],add[10000003],n; 6 void pushup(long long rt){sum[rt]=sum[rt<<1]+sum[rt<<1|1];} 7 void build(long long l,