I_like_play_eggy @ 2024-07-15 17:25:39
时隔 24 天再次爆肝此题,写了 5 小时共 180 行 3806 字节,样例 1 过了,样例 2 输出 10,求助
#include <bits/stdc++.h>
#define int long long
#define ls(p) (p<<1)
#define rs(p) (p<<1|1)
using namespace std;
const int maxn = 1e6 + 6;
const int inf = 1ll << 60;
struct SegmentTree // 线段树结构体
{
int lazy_add; // 增加 x
int lazy_upd; // 改为 x
int max_num; // 当前区间最大值
}
tree[maxn << 2]; // 开 4 倍空间
int num[maxn], n, m;
int op, l, r, x;
// 建树
void build(int pl, int pr, int p)
{
if (pl == pr) // 子节点
{
tree[p].lazy_upd = -inf; // 初始化为极小值
tree[p].max_num = num[pl]; // 子节点最大值为本身
return;
}
int mid = (pl + pr) >> 1;
// 对子区间建树
build(pl, mid, ls(p));
build(mid + 1, pr, rs(p));
// 更新区间最大值
tree[p].max_num = max(
tree[ls(p)].max_num,
tree[rs(p)].max_num
);
}
void addtag(int p, int x, bool isadd) // 打 Lazy_tag
{
if (isadd) // 如果是增加 x
{
tree[p].max_num += x; // 区间最大值增加 x
if (tree[p].lazy_upd != -inf) // 如果修改过数
{
tree[p].lazy_upd += x; // 修改的数增加 x
}
else
{
tree[p].lazy_add += x; // 增加的数增加 x
}
}
else // 如果是修改 x
{
tree[p].max_num = x; // 区间最大值改为 x
tree[p].lazy_upd = x; // 修改的数变为 x
tree[p].lazy_add = 0; // 增加的数变为 0
}
}
void pushdown(int pl, int pr, int p) // 下传 Lazy_tag
{
int mid = (pl + pr) >> 1;
if (tree[p].lazy_upd != -inf) // 如果修改过数
{
// 区间最大值改为 lazy_upd
tree[ls(p)].max_num = tree[p].lazy_upd;
// 修改的数改为 lazy_upd
tree[ls(p)].lazy_upd = tree[p].lazy_upd;
// 区间最大值改为 lazy_upd
tree[rs(p)].max_num = tree[p].lazy_upd;
// 修改的数改为 lazy_upd
tree[rs(p)].lazy_upd = tree[p].lazy_upd;
}
else
{
// 区间最大值增加 lazy_add
tree[ls(p)].max_num += tree[p].lazy_add;
// 增加的数增加 lazy_add
tree[ls(p)].lazy_add += tree[p].lazy_add;
// 区间最大值增加 lazy_add
tree[rs(p)].max_num += tree[p].lazy_add;
// 增加的数增加 lazy_add
tree[rs(p)].lazy_add += tree[p].lazy_add;
}
// 清零该节点 Lazy_tag
tree[p].lazy_add = 0;
tree[p].lazy_upd = -inf;
}
// 区间增加 x
void change_add(int pl, int pr, int p, int l, int r, int x)
{
if (l <= pl && pr <= r) // 完全覆盖此区间
{
addtag(p, x, 1); // 打 Lazy_tag
return;
}
pushdown(pl, pr, p); // 下传 lazy_tag
int mid = (pl + pr) >> 1;
if (l <= mid) // 包含左区间
{
change_add(pl, mid, ls(p), l, r, x);
}
if (r > mid) // 包含右区间
{
change_add(mid + 1, pr, rs(p), l, r, x);
}
}
// 区间修改为 x
void change_upd(int pl, int pr, int p, int l, int r, int x)
{
if (l <= pl && pr <= r) // 完全覆盖此区间
{
addtag(p, x, 0); // 打 Lazy_tag
return;
}
pushdown(pl, pr, p); // 下传 lazy_tag
int mid = (pl + pr) >> 1;
if (l <= mid) // 包含左区间
{
change_upd(pl, mid, ls(p), l, r, x);
}
if (r > mid) // 包含右区间
{
change_upd(mid + 1, pr, rs(p), l, r, x);
}
}
// 区间查询最大值
int query(int pl, int pr, int p, int l, int r)
{
if (l <= pl && pr <= r) // 完全覆盖此区间
{
return tree[p].max_num;
}
pushdown(pl, pr, p); // 下传 lazy_tag
int mid = (pl + pr) >> 1;
int s = -inf; // 初始化为极小值
if (l <= mid) // 包含左区间
{
s = max(s, query(pl, mid, ls(p), l, r));
}
if (r > mid) // 包含右区间
{
s = max(s, query(mid + 1, pr, rs(p), l, r));
}
return s; // 返回区间最大值
}
signed main()
{
scanf("%lld %lld", &n, &m);
for (int i = 1; i <= n; i ++)
{
scanf("%lld", &num[i]);
}
build(1, n, 1); // 建树
for (int i = 1; i <= m; i ++)
{
scanf("%lld %lld %lld", &op, &l, &r);
if (op == 1)
{
scanf("%lld", &x);
change_upd(1, n, 1, l, r, x); // 修改为 x
}
if (op == 2)
{
scanf("%lld", &x);
change_add(1, n, 1, l, r, x); // 增加 x
}
if (op == 3)
{
// 区间查询
printf("%lld\n", query(1, n, 1, l, r));
}
}
return 0;
}
by I_like_play_eggy @ 2024-07-15 17:32:49
@SiuuuCR7 @kevinZ99 救命