acwing 243. 一个简单的整数问题2 树状数组 线段树

地址 https://www.acwing.com/problem/content/description/244/

给定一个长度为N的数列A,以及M条指令,每条指令可能是以下两种之一:

1、“C l r d”,表示把 A[l],A[l+1],…,A[r] 都加上 d。

2、“Q l r”,表示询问 数列中第 l~r 个数的和。

对于每个询问,输出一个整数表示答案。

输入格式

第一行两个整数N,M。

第二行N个整数A[i]。

接下来M行表示M条指令,每条指令的格式如题目描述所示。

输出格式

对于每个询问,输出一个整数表示答案。

每个答案占一行。

数据范围
1≤N,M≤105,
|d|≤10000,
|A[i]|≤1000000000
输入样例:
10 5
1 2 3 4 5 6 7 8 9 10
Q 4 4
Q 1 10
Q 2 4
C 3 6 3
Q 2 4
输出样例:
4
55
9
15

解答

线段树模板  与上一题几乎一摸一样的板子 可以解决

可以说线段树就是解决此类问题的方案  缺点是相对树状数组 代码稍多

  1 #include <iostream>
  2 #include <algorithm>
  3 #include <string>
  4
  5 using namespace std;
  6
  7
  8 const int maxn = 1e5 + 6;
  9 int n;
 10 int a[maxn];
 11 int q;
 12
 13 struct node {
 14     int l, r;
 15     long long sum, lazy;
 16     void update(long long x) {
 17         sum += 1ll * (r - l + 1)*x;
 18         lazy += x;
 19     }
 20 }tree[maxn*4];
 21
 22 void push_up(int x) {
 23     tree[x].sum = tree[x << 1].sum + tree[x << 1 | 1].sum;
 24 }
 25
 26 void push_down(int x)
 27 {
 28     int lazyval = tree[x].lazy;
 29     if (lazyval) {
 30         tree[x << 1].update(lazyval);
 31         tree[x << 1 | 1].update(lazyval);
 32         tree[x].lazy = 0;
 33     }
 34
 35 }
 36
 37 void build(int x, int l, int r) {
 38     tree[x].l = l; tree[x].r = r;
 39     tree[x].sum = tree[x].lazy = 0;
 40     if (l == r) {
 41         tree[x].sum = a[l];
 42     }
 43     else {
 44         int mid = (l + r) / 2;
 45         build(x << 1, l, mid);
 46         build(x << 1 | 1, mid + 1, r);
 47         push_up(x);
 48     }
 49 }
 50
 51 void update(int x, int l, int r, long long val)
 52 {
 53     int L = tree[x].l, R = tree[x].r;
 54     if (l <= L && R <= r) {
 55         tree[x].update(val);
 56     }
 57     else {
 58         push_down(x);
 59         int mid = (L + R) / 2;
 60         if (mid >= l)  update(x << 1, l, r, val);
 61         if (r > mid) update(x << 1 | 1, l, r, val);
 62         push_up(x);
 63     }
 64 }
 65
 66 long long query(int x, int l, int r)
 67 {
 68     int L = tree[x].l, R = tree[x].r;
 69     if (l <= L && R <= r) {
 70         return tree[x].sum;
 71     }
 72     else {
 73         push_down(x);
 74         long long ans = 0;
 75         int mid = (L + R) / 2;
 76         if (mid >= l)  ans += query(x << 1, l, r);
 77         if (r > mid)  ans += query(x << 1 | 1, l, r);
 78         push_up(x);
 79         return ans;
 80     }
 81 }
 82
 83
 84
 85
 86 int main()
 87 {
 88     cin >> n >> q;
 89     for (int i = 1; i <= n; i++) {
 90         cin >> a[i];
 91     }
 92     build(1, 1, n);
 93
 94     for (int i = 1; i <= q; i++) {
 95         string s;
 96         int l, r, d, q;
 97         cin >> s;
 98         if (s == "Q") {
 99             cin >> l>>r;
100             cout << query(1, l, r) << endl;
101         }
102         else {
103             cin >> l >> r >> d;
104             update(1, l, r, d);
105         }
106     }
107
108     return 0;
109 }

线段树

原文地址:https://www.cnblogs.com/itdef/p/12270939.html

时间: 2024-10-08 11:03:20

acwing 243. 一个简单的整数问题2 树状数组 线段树的相关文章

AcWing:242. 一个简单的整数问题(树状数组)

给定长度为N的数列A,然后输入M行操作指令. 第一类指令形如“C l r d”,表示把数列中第l~r个数都加d. 第二类指令形如“Q X”,表示询问数列中第x个数的值. 对于每个询问,输出一个整数表示答案. 输入格式 第一行包含两个整数N和M. 第二行包含N个整数A[i]. 接下来M行表示M条指令,每条指令的格式如题目描述所示. 输出格式 对于每个询问,输出一个整数表示答案. 每个答案占一行. 数据范围 1≤N,M≤1051≤N,M≤105,|d|≤10000|d|≤10000,|A[i]|≤1

AcWing 242 一个简单整数问题(区间修改 单点查询)

原题 该题涉及树状数组又一串操作: ① 区间修改 运用差分的思想,我们新建了一个数组b,初始化为零,对于每个指令"C l r d",我们只需将其转化为以下操作: 1.把b[l]加上d 2.再把b[r+1]减去d inline void add(int x,int y) { for(;x<=n;x+=x&-x) { c[x]+=y; } } add(l,j); add(r+1,-j); ② 单点查询 执行了以上操作后,b数组的前缀和b[1~x]就代表了该指令对a[x]的影响

一个简单的整数问题2

题意:给定一个长度为N的数列A,以及M条指令,每条指令可能是以下两种之一: 1.“C l r d”,表示把 A[l],A[l+1],…,A[r] 都加上 d. 2.“Q l r”,表示询问 数列中第 l~r 个数的和. 对于每个询问,输出一个整数表示答案. 思路:用树状数组进行区间操作.用一个数组b[i]代表当操作为[l,r]同时d操作时则b[r+1]-d,b[l]+d.这样求的前后缀未变.树状数组维护b前缀,相当于只有b[l,r]变了, 然后再用个树状数组维护i*b[i]的前缀.所以求区间[l

返回一个二维整数组中最大子数组的和

题目:返回一个二维整数组中最大子数组的和 实验思路 根据老师上课给出的3*6的数据 我们决定设计一个3*6行的二维数组进行计算,依次进行比较 将最大子数组的和返回 代码 1 #include <iostream.h> 2 int main() 3 { 4 int a[3][6];//定义一个3*6的二维数组 5 int max; 6 int s;//求和 7 int count; 8 int b[3][7]; 9 cout<<"请输入二维数组(3*6)中的元素:"

树状数组的简单运用

树状数组是一个比较优秀的数据结构,可以在O(log n)的情况下完成一些对数列的维护~~ 而且代码简单易懂,所以树状数组在OI竞赛中对于解决区间问题是十分常用的数据结构 接下来是一些例题: A.校门外的树 题目描述 某校大门外长度为L的马路上有一排树,每两棵相邻的树之间的间隔都是1米.我们可以把马路看成一个数轴,马路的一端在数轴0的位置,另一端在L的位置:数轴上的每个整数点,即0,1,2,--,L,都种有一棵树. 由于马路上有一些区域要用来建地铁.这些区域用它们在数轴上的起始点和终止点表示.已知

【BZOJ2683】简单题 [分治][树状数组]

简单题 Time Limit: 50 Sec  Memory Limit: 128 MB[Submit][Status][Discuss] Description 你有一个N*N的棋盘,每个格子内有一个整数,初始时的时候全部为0,现在需要维护两种操作: 命令 参数限制 内容 1 x y A 1<=x,y<=N,A是正整数 将格子x,y里的数字加上A 2 x1 y1 x2 y2 1<=x1<= x2<=N 1<=y1<= y2<=N 输出x1 y1 x2 y2

BZOJ2683: 简单题(CDQ分治 + 树状数组)

BZOJ2683: 简单题(CDQ分治 + 树状数组) 题意: 你有一个\(N*N\)的棋盘,每个格子内有一个整数,初始时的时候全部为\(0\),现在需要维护两种操作: 命令 参数限制 内容 \(1\ x\ y\ A\) \(1\le x,y \le N\),A是正整数 将格子\(x,y\)里的数字加上\(A\) \(2\ x1\ y1\ x2\ y2\) \(1\le x1\le x2\le N,1\le y1\le y2\le N\) 输出\(x1\ y1\ x2\ y2\)这个矩形内的数字

(简单) POJ 3321 Apple Tree,树链剖分+树状数组。

Description There is an apple tree outside of kaka's house. Every autumn, a lot of apples will grow in the tree. Kaka likes apple very much, so he has been carefully nurturing the big apple tree. The tree has N forks which are connected by branches.

POJ2481 Cows 树状数组的简单应用

题意给了你N头牛,每头牛的强壮值是一个区间[s,e],如果第 i 头牛比第 j 头牛强壮那么必须满足 Si <= Sj and Ej <= Ei and Ei - Si > Ej - Sj: 为了满足这三个条件我们进行排序,先以e降序排为先决条件,若e相等则让s升序排列,如此即可满足三个条件,这道题目任意两头牛的强壮值区间有可能完全一样,这样就不需要重新用树状数组求一次和了,直接赋值即可,这样可以省很多时间,因为已经排序处理了,所以即便区间相等的  肯定就是相邻的,所以直接扫一遍即可,若