码迷,mamicode.com
首页 > 其他好文 > 详细

luogu SP1043 GSS1 - Can you answer these queries I

时间:2020-05-06 20:03:08      阅读:53      评论:0      收藏:0      [点我收藏+]

标签:swap   iostream   端点   sp1   algo   turn   ++   stream   swa   

//单点修改  pushup
//查询区间内的最大字段和
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 500010;
int n, m;
int w[N];
struct Node
{
	//端点
	int l, r;
	int sum;//区间和
	//最大前缀和
	//分两种:没有超过mid,超过mid
	//没有超过mid的就是,当前区间左儿子的最大字段和
	//超过mid的就是,左边的sum+右边的lmax
	int lmax;
	//最大后缀和
	////横跨左右区间的最大子段和==左子区间的最大后缀和+右子区间的最大前缀和
	int rmax;
	//最大连续子段和
	//max(左子区间的最大子段和,右子区间的最大子段和,横跨左右区间的最大子段和)
	int tmax;
} tr[N * 4];
//u是l和r的父节点
void pushup(Node &u, Node &l, Node &r)
{
	//总和
	u.sum = l.sum + r.sum;
	//最大前缀
	u.lmax = max(l.lmax, l.sum + r.lmax);
	//最大后缀
	u.rmax = max(r.rmax, r.sum + l.rmax);
	//最大子段和
	u.tmax = max(max(l.tmax, r.tmax), l.rmax + r.lmax);
}

void pushup(int u)
{
	//根节点,左子节点,右子节点
	pushup(tr[u], tr[u << 1], tr[u << 1 | 1]);
}
//
void build(int u, int l, int r)
{
	//如果是叶节点
	if (l == r)
		//左右节点,总和(就一个数),最大前缀和,最大后缀和,最大子段和
		tr[u] = {l, r, w[r], w[r], w[r], w[r]};
	else
	{
		tr[u] = {l, r};
		int mid = l + r >> 1;
		build(u << 1, l, mid), build(u << 1 | 1, mid + 1, r);
		pushup(u);
	}
}
//修改函数
//  在x这个位置,把它改成v
int modify(int u, int x, int v)
{
	//如果到了叶节点
	if (tr[u].l == x && tr[u].r == x)
		tr[u] = {x, x, v, v, v, v};
	else
	{
		int mid = tr[u].l + tr[u].r >> 1;
		if (x <= mid)
			modify(u << 1, x, v);
		else
			modify(u << 1 | 1, x, v);
		pushup(u);
	}
}
//查询
//数中查询到的节点编号,左端点,右端点
Node query(int u, int l, int r)
{
	//如果已经呗包含了,就返回
	if (tr[u].l >= l && tr[u].r <= r)
		return tr[u];
	else
	{
		//中点
		int mid = tr[u].l + tr[u].r >> 1;
		//完全在左边
		if (r <= mid)
			return query(u << 1, l, r);
		//完全在右边
		else if (l > mid)
			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;
			pushup(res, left, right);
			return res;
		}
	}
}
int main()
{
	cin>>n;
	for (int i = 1; i <= n; i ++ )
		scanf("%d", &w[i]);
	build(1, 1, n);
	cin>>m;
	int k, x, y;
	while (m -- )
	{
		k=1;
		cin>>x>>y;
		if (k == 1)
		{
			if (x > y)
				swap(x, y);
			printf("%d\n", query(1, x, y).tmax);
		}
		//修改
		else
			modify(1, x, y);
	}
	return 0;
}

luogu SP1043 GSS1 - Can you answer these queries I

标签:swap   iostream   端点   sp1   algo   turn   ++   stream   swa   

原文地址:https://www.cnblogs.com/QingyuYYYYY/p/12838294.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!