求助,样例2没过
查看原帖
求助,样例2没过
1126325
Indestructible楼主2024/7/15 17:25

时隔 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;
}
2024/7/15 17:25
加载中...