网址如下:
P3372 【模板】线段树 1 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
题如其名
昨天做了一道开关(也是线段树的)
想着今天复习一下
代码如下:
#include
using namespace std;
typedef long long ll;
ll query(int l, int r, int p, int cl, int cr);
void update(int l, int r, ll d, int p, int cl, int cr);
void build(int l, int r, int p);
ll tree[100000000], mark[100000000], element[100001], k;
int n, m, x, y;
int main(void)
{
//输入
cin >> n >> m;
for(int i = 1; i <= n; i++)
cin >> element[i];
//处理
build(1, n, 1);
for(int i = 0; i < m; i++)
{
int n_switch;
cin >> n_switch;
if(n_switch == 1)
{
cin >> x >> y >> k;
update(x, y, k, 1, 1, n);
}
else
{
cin >> x >> y;
cout << query(x, y, 1, 1, n) << endl;
}
}
return 0;
}
ll query(int l, int r, int p, int cl, int cr)
{
if(cl > r || cr < l)
return 0;
if(cl >= l && cr <= r)
return tree[p];
else
{
int mid = (cl + cr) / 2;
tree[2 * p] += mark[p] * (ll)(mid - cl + 1), tree[2 * p + 1] += mark[p] * (ll)(cr - mid);
mark[2 * p] += mark[p], mark[2 * p + 1] += mark[p];
mark[p] = 0;
return query(l, r, 2 * p, cl, mid) + query(l, r, 2 * p + 1, mid + 1, cr);
}
}
void update(int l, int r, ll d, int p, int cl, int cr)
{
if(cl > r || cr < l)
return;
if(cl >= l && cr <= r)
{
mark[p] += d;
tree[p] += d * (ll)(cr - cl + 1);
}
else
{
int mid = (cl + cr) / 2;
tree[2 * p] += mark[p] * (ll)(mid - cl + 1), tree[2 * p + 1] += mark[p] * (ll)(cr - mid);
mark[2 * p] += mark[p], mark[2 * p + 1] += mark[p];
mark[p] = 0;
update(l, r, d, 2 * p, cl, mid), update(l, r, d, 2 * p + 1, mid + 1, cr);
tree[p] = tree[2 * p] + tree[2 * p + 1];
}
}
void build(int l, int r, int p)
{
if(l < r)
{
int mid = (l + r) / 2;
build(l, mid, 2 * p), build(mid + 1, r, 2 * p + 1);
tree[p] = tree[2 * p] + tree[2 * p + 1];
}
else
tree[p] = element[l];
}