AcWing245. 你能回答这些问题吗 线段树详解
创始人
2024-02-17 17:53:29
0

3.2线段树

在这里插入图片描述

例题分析

245. 你能回答这些问题吗 - AcWing题库

**题意:**给一条序列,如何动态维护区间的最大子段和,包括询问某区间的最大字段和和修改某个数。

分析:线段树struct保留什么信息。能否通过左右儿子的这些信息求出父节点的所有信息。

首先毋庸置疑的是左右端点和最大连续子段和。

struct node{int l,r;int tmax;
}

然后我们思考,能不能得到父节点的信息。

​ 如图,假设我们已知左右孩子的最大子段和,同时假设父节点的最大字段和为图中绿色区域,我们发现,父节点的最大连续子段和可能是跨区间的,我们没办法通过孩子的信息得到父亲的信息,所以我们考虑添加维护的信息。

我们维护每个区间的最大前缀和和最大后缀和,如下图,横跨整个区间的子段和可以通过左边的最大后缀和加上右边的最大前缀和得到。

此时我们的结构体变成了这样:

struct node{int l,r;int tmax;//区间的最大字段和int lmax;//区间的最大前缀和int rmax;//区间的最大后缀和
}

那我们再回到刚才的思考,通过这些信息如何得到父节点的信息。

​ 那么,结合三个信息,我们可以用三个值(左儿子的最大子段和、右儿子的最大子段和、左儿子的最大后缀和加右儿子的最大前缀和)取max来得到。这里信息全面吗?答案是全面的,不过是对于区间最大子段和来说;假设最大子段和在左区间,那么(如下图)1、2、3区间(前缀、中间、后缀)能够完全表示,4、5、6同理,除了这些情况,再加上跨区间的情况,那么这些情况取max就是确定的最大值。

接下来我们再思考,我们新加入的两个信息是否能通过儿子节点求出来, 假设我们的最大前缀和是跨区间的时候,那么情况变成了这样,所以我们还需要加一个信息:区间和。

而区间和我们是可以直接求的,因此,我们每个信息都能得到了,分析完毕。

struct node{int l,r;int tmax;//区间的最大字段和int lmax;//区间的最大前缀和int rmax;//区间的最大后缀和int sum;//区间和
}

思考模式:首先我们想如何得到我们想要的答案,当添加了想要的信息之后,还要思考如何得到想要的信息,最后直到全部信息都能通过左右孩子得到。

参考代码:

#include 
using namespace std;const int N = 5e6 + 5;
vector ve(N);
int n, k;struct node {int l, r;int tmax;//区间的最大字段和int lmax;//区间的最大前缀和int rmax;//区间的最大后缀和int sum;//区间和
} tr[4 * N];void pushup(node& u, node& l, node& r) {//函数重载u.tmax = max(max(l.tmax, r.tmax), l.rmax + r.lmax);u.lmax = max(l.lmax, l.sum + r.lmax);u.rmax = max(r.rmax, r.sum + l.rmax);u.sum = l.sum + r.sum;
}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,ve[l],ve[l],ve[l],ve[l]};//到子节点直接存下所有信息return;}tr[u] = {l, r};int mid = l + r >> 1;build(u << 1, l, mid);build(u << 1 | 1, mid + 1, r);pushup(u);//这里想要pushup
}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)return query(u << 1 | 1, l, r);//答案完全在右区间else{auto R = query(u << 1, l, r);auto L=query(u << 1 | 1, l, r); //答案想要左右区间的信息合并才能得到node res;pushup(res, R, L);//合并左右区间信息return res;}
}void modify(int u,int x,int val){if(tr[u].l==x&&tr[u].r==x)tr[u] = {x,x,val,val,val,val};else{int mid = tr[u].l + tr[u].r >> 1;if(x<=mid)modify(u << 1, x, val);elsemodify(u << 1 | 1, x, val);pushup(u);}
}int main() {cin >> n >> k;for (int i = 1; i <= n; i++) {cin >> ve[i];}//cout << "x" <int q;cin >> q;if (q == 1) {int l, r;cin >> l >> r;if(l>r)swap(l, r);cout<int x, y;cin >> x >> y;modify(1, x, y);}}
}

相关内容

热门资讯

喜欢穿一身黑的男生性格(喜欢穿... 今天百科达人给各位分享喜欢穿一身黑的男生性格的知识,其中也会对喜欢穿一身黑衣服的男人人好相处吗进行解...
发春是什么意思(思春和发春是什... 本篇文章极速百科给大家谈谈发春是什么意思,以及思春和发春是什么意思对应的知识点,希望对各位有所帮助,...
网络用语zl是什么意思(zl是... 今天给各位分享网络用语zl是什么意思的知识,其中也会对zl是啥意思是什么网络用语进行解释,如果能碰巧...
为什么酷狗音乐自己唱的歌不能下... 本篇文章极速百科小编给大家谈谈为什么酷狗音乐自己唱的歌不能下载到本地?,以及为什么酷狗下载的歌曲不是...
家里可以做假山养金鱼吗(假山能... 今天百科达人给各位分享家里可以做假山养金鱼吗的知识,其中也会对假山能放鱼缸里吗进行解释,如果能碰巧解...
华为下载未安装的文件去哪找(华... 今天百科达人给各位分享华为下载未安装的文件去哪找的知识,其中也会对华为下载未安装的文件去哪找到进行解...
四分五裂是什么生肖什么动物(四... 本篇文章极速百科小编给大家谈谈四分五裂是什么生肖什么动物,以及四分五裂打一生肖是什么对应的知识点,希...
怎么往应用助手里添加应用(应用... 今天百科达人给各位分享怎么往应用助手里添加应用的知识,其中也会对应用助手怎么添加微信进行解释,如果能...
苏州离哪个飞机场近(苏州离哪个... 本篇文章极速百科小编给大家谈谈苏州离哪个飞机场近,以及苏州离哪个飞机场近点对应的知识点,希望对各位有...
客厅放八骏马摆件可以吗(家里摆... 今天给各位分享客厅放八骏马摆件可以吗的知识,其中也会对家里摆八骏马摆件好吗进行解释,如果能碰巧解决你...