2024.2.6 寒假训练记录(20)

文章目录

  • 牛客 寒假集训2G Tokitsukaze and Power Battle (easy)
  • 牛客 寒假集训2H Tokitsukaze and Power Battle (hard)

牛客 寒假集训2G Tokitsukaze and Power Battle (easy)

题目链接

好感动,调了好久的一题终于调出来了

大体是线段树,pushup的地方稍微修改一下就好了

要注意的点是:线段树更新(pushup)的时候,需要用两个子结点重新计算父结点,不可以再保留原来的最大值了!这个点卡了很久很久

#include 

using namespace std;

#define int long long
using i64 = long long;

typedef pair<int, int> PII;
typedef pair<double, double> PDD;
typedef pair<int, PII> PIII;

const int N = 5e5 + 10;

vector<int> a(N);

struct Node
{
	// v:[l,r]中的合法答案
	int l, r, sum, v;
}tr[N * 4];

void pushup(Node &u, Node &left, Node &right)
{
	u.l = left.l, u.r = right.r;
	u.sum = left.sum + right.sum;
	u.v = max(left.v, max(left.sum + right.v, left.sum - a[right.l]));
}

void pushup(int u)
{
	pushup(tr[u], tr[u << 1], tr[u << 1 | 1]);
}

void build(int u, int l, int r)
{
	tr[u] = {l, r, 0, -0x3f3f3f3f3f3f3f3f};
	if (l == r)
	{
		tr[u].sum = a[l];
		return;
	}
	int mid = l + r >> 1;
	build(u << 1, l, mid), build(u << 1 | 1, mid + 1, r);
	pushup(u);
}

void modify(int u, int pos, int x) // 把pos位置的值变成x
{
	if (tr[u].l == pos && tr[u].r == pos)
	{
		tr[u].sum = x;
		return;
	}
	int mid = tr[u].l + tr[u].r >> 1;
	if (pos <= mid) modify(u << 1, pos, x);
	else modify(u << 1 | 1, pos, x);
	pushup(u);
}

Node query(int u, int l, int r)
{
	if (tr[u].l >= l && tr[u].r <= r) return tr[u];
	int mid = tr[u].l + tr[u].r >> 1;
	if (r <= mid) return query(u << 1, l, r);
	else if (l >= mid + 1) return query(u << 1 | 1, l, r);
	else
	{
		auto left = query(u << 1, l, r);
		auto right = query(u << 1 | 1, l, r);
		Node res = {l, r, 0, -0x3f3f3f3f3f3f3f3f};
		pushup(res, left, right);
		return res;
	}
}

void solve()
{
	int n, q;
	cin >> n >> q;
	for (int i = 1; i <= n; i ++ ) cin >> a[i];
	build(1, 1, n);
	while (q -- )
	{
		int op, x, y;
		cin >> op >> x >> y;
		if (op == 1)
		{
			a[x] = y;
			modify(1, x, y);
		}
		else
		{
			auto res = query(1, x, y);
			cout << res.v << '\n';
		}
	}
}

signed main()
{
	ios::sync_with_stdio(false);
	cin.tie(0), cout.tie(0);

	int t = 1;
	cin >> t;
	while (t -- )
	{
		solve();
	}
}

牛客 寒假集训2H Tokitsukaze and Power Battle (hard)

题目链接

突然发现线段树好像也就那样,线段树最大的难点是在pushup这里,其他都是板子罢了,主要是思维要清晰,能分清楚各种情况

#include 

using namespace std;

#define int long long
using i64 = long long;

typedef pair<int, int> PII;
typedef pair<double, double> PDD;
typedef pair<int, PII> PIII;

const int N = 5e5 + 10;
const int inf = 0x3f3f3f3f3f3f3f3f;

vector<int> a(N);

struct Node
{
	int l, r, sum;
	int lmin, rmax; // 包含区间左端点的最小子段和和包含区间右端点的最大子段和
	int ansl, ansr, ansall; // 包含区间左/右端点/整段区间的最大答案
	int ans; // 整个区间最大答案
}tr[N * 4];

void pushup(Node &u, Node &left, Node &right)
{
	u.l = left.l, u.r = right.r;
	u.sum = left.sum + right.sum;
	u.lmin = min(left.lmin, left.sum + right.lmin);
	u.rmax = max(right.rmax, right.sum + left.rmax);
	u.ansl = max({left.ansl, left.sum + right.ansl, left.sum - right.lmin, left.ansall - right.lmin});
	u.ansr = max({right.ansr, left.ansr - right.sum, left.rmax - right.sum, left.rmax + right.ansall});
	u.ansall = max({left.sum - right.sum, left.ansall - right.sum, left.sum + right.ansall});
	u.ans = max({left.ans, right.ans, left.rmax - right.lmin, left.rmax + right.ansl, left.ansr - right.lmin});
}

void pushup(int u)
{
	pushup(tr[u], tr[u << 1], tr[u << 1 | 1]);
}

void build(int u, int l, int r)
{
	tr[u] = {l, r, 0, inf, -inf, -inf, -inf, -inf, -inf};
	if (l == r)
	{
		tr[u].sum = tr[u].lmin = tr[u].rmax = a[l];
		return;
	}
	int mid = l + r >> 1;
	build(u << 1, l, mid), build(u << 1 | 1, mid + 1, r);
	pushup(u);
}

void modify(int u, int pos, int x) // 把pos位置的值变成x
{
	if (tr[u].l == pos && tr[u].r == pos)
	{
		tr[u].sum = tr[u].lmin = tr[u].rmax = x;
		return;
	}
	int mid = tr[u].l + tr[u].r >> 1;
	if (pos <= mid) modify(u << 1, pos, x);
	else modify(u << 1 | 1, pos, x);
	pushup(u);
}

Node query(int u, int l, int r)
{
	if (tr[u].l >= l && tr[u].r <= r) return tr[u];
	int mid = tr[u].l + tr[u].r >> 1;
	if (r <= mid) return query(u << 1, l, r);
	else if (l >= mid + 1) return query(u << 1 | 1, l, r);
	else
	{
		auto left = query(u << 1, l, r);
		auto right = query(u << 1 | 1, l, r);
		Node res = {l, r, 0, -inf};
		pushup(res, left, right);
		return res;
	}
}

void solve()
{
	int n, q;
	cin >> n >> q;
	for (int i = 1; i <= n; i ++ ) cin >> a[i];
	build(1, 1, n);
	while (q -- )
	{
		int op, x, y;
		cin >> op >> x >> y;
		if (op == 1)
		{
			a[x] = y;
			modify(1, x, y);
		}
		else
		{
			auto res = query(1, x, y);
			cout << res.ans << '\n';
		}
	}
}

signed main()
{
	ios::sync_with_stdio(false);
	cin.tie(0), cout.tie(0);

	int t = 1;
	cin >> t;
	while (t -- )
	{
		solve();
	}
}

你可能感兴趣的:(2024寒假训练记录,算法)