本代码测试通过P3368题
如有错误,欢迎指出(我觉得没有,毕竟都AC了,哈哈)
结构体参数解释
- lran:节点表示原数组的区间左端下标
- rran:节点表示原数组的区间右端下标
- lazy:懒惰标记,区间修改时用于标记本节点已被修改,但是其子节点未被修改的点
- val:当前节点所表示的数值
函数解释
- glson:获取当前节点的左儿子(本代码中,线段树数组的0号下标不放置节点,因此满足 l s o n = f a t h e r ∗ 2 lson=father*2 lson=father∗2)
- grson:获取当前节点的右儿子
- update:根据当前节点的子节点更新当前节点(节点u)
- pushDown:lazy标记下传。(因为本题对区间的操作是累加,因此lazy是可加的,因此只需要在查询的时候下传标记即可,修改区间时无需下传)
#include
#define maxn 500010
using namespace std;
struct node {
int lran, rran, lazy;
long val;
node() { lazy = 0; }
};
int arr[maxn] = { 0 };
// 构建线段树数组
node tree[maxn * 4] = {};
inline int glson(int u) { return u << 1; }
inline int grson(int u) { return u << 1 | 1; }
inline void update(int u) { tree[u].val = tree[glson(u)].val + tree[grson(u)].val; }
inline void pushDown(int u) {
// 如果是叶子节点,无需下传
if (tree[u].lran == tree[u].rran) {
tree[u].lazy = 0;
return;
}
// 下传标记
int lson = glson(u), rson = grson(u);
tree[lson].lazy += tree[u].lazy;
tree[rson].lazy += tree[u].lazy;
// 数值下传
tree[lson].val += (tree[lson].rran - tree[lson].lran + 1) * tree[u].lazy;
tree[rson].val += (tree[rson].rran - tree[rson].lran + 1) * tree[u].lazy;
// 清空当前lazy
tree[u].lazy = 0;
}
// 建树
void build(int u, int lran, int rran) {
tree[u].lran = lran, tree[u].rran = rran;
// 如果是叶子节点
if (lran == rran) {
tree[u].val = arr[lran];
return;
}
int mid = lran + rran >> 1;
build(glson(u), lran, mid);
build(grson(u), mid + 1, rran);
update(u);
}
// 单点修改
void add(int u, int pos, int k) {
// 到达叶子节点
if (tree[u].lran == tree[u].rran) {
tree[u].val += k;
return;
}
int mid = tree[u].lran + tree[u].rran >> 1;
if (pos <= mid) add(glson(u), pos, k);
else add(grson(u), pos, k);
update(u);
}
// 区间修改
void modify(int u, int lran, int rran, int k) {
// cout << "u=" << u << endl;
if (lran == tree[u].lran && rran == tree[u].rran) {
tree[u].lazy += k;
tree[u].val += k * (tree[u].rran - tree[u].lran + 1);
return;
}
int mid = tree[u].lran + tree[u].rran >> 1;
if (mid >= rran) modify(glson(u), lran, rran, k);
else if(mid < lran) modify(grson(u), lran, rran, k);
else {
modify(glson(u), lran, mid, k);
modify(grson(u), mid + 1, rran, k);
}
update(u);
}
// 区间查询
long search(int u, int lran, int rran) {
// 当前节点有lazy,下传
if (tree[u].lazy) pushDown(u);
// 完全不在区间内
if (lran < tree[u].lran || rran > tree[u].rran) return 0;
// 完全包含
if (lran <= tree[u].lran && rran >= tree[u].rran) return tree[u].val;
long val = 0;
// 左区间交
if (tree[glson(u)].rran >= lran) val += search(glson(u), lran, rran);
// 右区间交
if (tree[grson(u)].lran <= rran) val += search(grson(u), lran, rran);
return val;
}
// 单点查询
long query(int u, int pos) {
// 当前节点有lazy,下传
if (tree[u].lazy) pushDown(u);
if (tree[u].lran == tree[u].rran) return tree[u].val;
int mid = tree[u].lran + tree[u].rran >> 1;
if (pos <= mid) return query(glson(u), pos);
else return query(grson(u), pos);
}
int main() {
int N, M, L, R, k, idx, op;
cin >> N >> M;
for (int i = 0; i < N; ++i) cin >> arr[i];
// 建立树
build(1, 0, N - 1);
for (int i = 0; i < M; ++i) {
cin >> op;
// 单点修改
if (op == 1) {
cin >> L >> R >> k;
modify(1, L - 1, R - 1, k);
}
// 单点查询
else {
cin >> idx;
cout << query(1, idx - 1) << endl;
}
}
return 0;
}
#include
#define maxn 500010
using namespace std;
int arr[maxn] = { 0 };
struct node {
int lran, rran, lazy;
long val;
node* lson, * rson;
node() { lson = nullptr, rson = nullptr, lazy = 0; }
};
inline void update(node* u) { u->val = u->lson->val + u->rson->val; }
inline void pushDown(node* u) {
// 如果是叶子节点
if (u->lran == u->rran) {
u->lazy = 0;
return;
}
// 下传标记
u->lson->lazy += u->lazy;
u->rson->lazy += u->lazy;
// 修改赋值
u->lson->val += (u->lson->rran - u->lson->lran + 1) * u->lazy;
u->rson->val += (u->rson->rran - u->rson->lran + 1) * u->lazy;
// 清空lazy
u->lazy = 0;
}
// 建树
node* build(int lran, int rran) {
node* u = new node();
u->lran = lran, u->rran = rran;
// 到达叶节点
if (lran == rran) {
u->val = arr[lran];
return u;
}
int mid = (lran + rran) >> 1;
u->lson = build(lran, mid);
u->rson = build(mid + 1, rran);
// 更新节点
update(u);
return u;
}
// 修改区间
void modify(node* u, int lran, int rran, int k) {
// 完全覆盖
if (u->lran == lran && u->rran == rran) {
u->val += k * (rran - lran + 1);
u->lazy += k;
return;
}
int mid = (u->lran + u->rran) >> 1;
if (mid >= rran) {
modify(u->lson, lran, rran, k);
}
else if (mid < lran) {
modify(u->rson, lran, rran, k);
}
else {
modify(u->lson, lran, mid, k);
modify(u->rson, mid + 1, rran, k);
}
// 更新节点
update(u);
}
// 单点查询
long query(node* u, int pos) {
// 下传标记
if(u->lazy) pushDown(u);
if (u->lran == u->rran) return u->val;
int mid = (u->lran + u->rran) >> 1;
if (pos <= mid) return query(u->lson, pos);
else return query(u->rson, pos);
}
int main() {
int N, M, op, L, R, k, idx;
cin >> N >> M;
for (int i = 0; i < N; ++i) cin >> arr[i];
node* head = build(0, N - 1);
for (int i = 0; i < M; ++i) {
cin >> op;
if (op == 1) {
cin >> L >> R >> k;
modify(head, L - 1, R - 1, k);
}
else {
cin >> idx;
cout << query(head, idx - 1) << endl;
}
}
return 0;
}