AcWing:245. 你能回答这些问题吗(线段树最大子段和)
给定长度为N的数列A,以及M条指令,每条指令可能是以下两种之一:
1、“1 x y”,查询区间 [x,y] 中的最大连续子段和,即 maxx≤l≤r≤ymaxx≤l≤r≤y{∑ri=lA[i]∑i=lrA[i]}。
2、“2 x y”,把 A[x] 改成 y。
对于每个查询指令,输出一个整数表示答案。
输入格式
第一行两个整数N,M。
第二行N个整数A[i]。
接下来M行每行3个整数k,x,y,k=1表示查询(此时如果x>y,请交换x,y),k=2表示修改。
输出格式
对于每个查询指令输出一个整数表示答案。
每个答案占一行。
数据范围
N≤500000,M≤100000N≤500000,M≤100000
输入样例:
5 3
1 2 -3 4 5
1 2 3
2 2 -1
1 3 2
输出样例:
2
-1
算法:线段树最大子段和
代码:
#include <iostream>
#include <cstdio> using namespace std; #define INF 0x3f3f3f3f const int maxn = 5e5+; struct node {
int ms; //存储当前区间最大子段和
int lmax; //左边得前缀和
int rmax //右边得前缀和
int sum; //这个区间的总和
}tree[maxn << ]; int arr[maxn];
int n, m; void pushup(int root) { //参数的解释:
tree[root].sum = tree[root << ].sum + tree[root << | ].sum; //左子数的总和 + 右子树的总和
tree[root].lmax = max(tree[root << ].lmax, tree[root << ].sum + tree[root << | ].lmax); //左子数左边得前缀和,左子数得总和 + 右子树左边的前缀和
tree[root].rmax = max(tree[root << | ].rmax, tree[root << | ].sum + tree[root << ].rmax); //右子树右边的前缀和,右子树的总和 + 左子数右边的前缀和
tree[root].ms = max(max(tree[root << ].ms, tree[root << | ].ms), tree[root << ].rmax + tree[root << | ].lmax); //左子树的区间最大子段和,右子树的区间最大子段和,左子数右边的前缀和 + 右子树左边的前缀和
} void build(int root, int l ,int r) {
if(l == r) {
tree[root].sum = arr[l];
tree[root].ms = arr[l];
tree[root].lmax = arr[l];
tree[root].rmax = arr[l];
return;
}
int mid = (l + r) >> ;
build(root << , l ,mid);
build(root << | , mid + , r);
pushup(root);
} void update(int root, int l, int r, int x, int y) {
if(l == r) {
tree[root].sum = y;
tree[root].ms = y;
tree[root].lmax = y;
tree[root].rmax = y;
return;
}
int mid = (l + r) >> ;
if(x <= mid) {
update(root << , l, mid, x, y);
} else {
update(root << | , mid + , r, x, y);
}
pushup(root);
} struct node query(int root, int l, int r, int x, int y) {
if(x <= l && r <= y) {
return tree[root];
}
int mid = (l + r) >> ;
struct node a, b, c;
//首先初始化,因为有可能进入第一种或者是第二种情况,那么其中有一个变量就用不到
a.ms = a.lmax = a.rmax = a.sum = -INF;
b.ms = b.lmax = b.rmax = b.sum = -INF;
c.ms = c.lmax = c.rmax = -INF;
c.sum = ;
//分三种情况:
if(x <= mid && y <= mid) {
a = query(root << , l, mid, x, y);
c.sum += a.sum;
} else if(x > mid && y > mid) {
b = query(root << | , mid + , r, x, y);
c.sum += b.sum;
} else {
a = query(root << , l, mid, x, y);
b = query(root << | , mid + , r, x, y);
c.sum += a.sum + b.sum;
}
//解释同上...
c.ms = max(c.ms, max(a.rmax + b.lmax, max(a.ms, b.ms)));
c.lmax = max(c.lmax, max(a.lmax, a.sum + b.lmax));
c.rmax = max(c.rmax, max(b.rmax, b.sum + a.rmax));
return c;
} int main() {
scanf("%d %d", &n, &m);
for(int i = ; i <= n; i++) {
scanf("%d", &arr[i]);
}
build(, , n);
while(m--) {
int q, x, y;
scanf("%d %d %d", &q, &x, &y);
if(q == ) {
if(x > y) { //题目中有解释...
swap(x, y);
}
printf("%d\n", query(, , n, x, y).ms);
} else {
update(, ,n, x, y);
}
}
return ;
}
AcWing:245. 你能回答这些问题吗(线段树最大子段和)的更多相关文章
- Acwing 245.你能回答这些问题吗
题目描述 给定长度为N的数列A,以及M条指令,每条指令可能是以下两种之一: 1."1 x y",查询区间 [x,y] 中的最大连续子段和,即 maxx≤l≤r≤y{∑ri=lA[i ...
- ACwing 你能回答这些问题吗(线段树求最大连续字段和)
给定长度为N的数列A,以及M条指令,每条指令可能是以下两种之一: 1.“1 x y”,查询区间 [x,y] 中的最大连续子段和,即 maxx≤l≤r≤ymaxx≤l≤r≤y{∑ri=lA[i]∑i=l ...
- acwing 243. 一个简单的整数问题2 树状数组 线段树
地址 https://www.acwing.com/problem/content/description/244/ 给定一个长度为N的数列A,以及M条指令,每条指令可能是以下两种之一: 1.“C l ...
- AcWing 243. 一个简单的整数问题2 (树状数组)打卡
题目:https://www.acwing.com/problem/content/244/ 题意:区间加,区间查询 思路:我们把原先那个差分数组分解一下 ∑i=1x∑j=1ib[j]=∑i=1x(x ...
- AcWing:242. 一个简单的整数问题(树状数组)
给定长度为N的数列A,然后输入M行操作指令. 第一类指令形如“C l r d”,表示把数列中第l~r个数都加d. 第二类指令形如“Q X”,表示询问数列中第x个数的值. 对于每个询问,输出一个整数表示 ...
- AcWing:148. 合并果子(哈夫曼树)
在一个果园里,达达已经将所有的果子打了下来,而且按果子的不同种类分成了不同的堆. 达达决定把所有的果子合成一堆. 每一次合并,达达可以把两堆果子合并到一起,消耗的体力等于两堆果子的重量之和. 可以看出 ...
- AcWing 107. 超快速排序(归并排序 + 逆序对 or 树状数组)
在这个问题中,您必须分析特定的排序算法----超快速排序. 该算法通过交换两个相邻的序列元素来处理n个不同整数的序列,直到序列按升序排序. 对于输入序列9 1 0 5 4,超快速排序生成输出0 1 4 ...
- AcWing:246. 区间最大公约数(线段树 + 增量数组(树状数组) + 差分序列)
给定一个长度为N的数列A,以及M条指令,每条指令可能是以下两种之一: 1.“C l r d”,表示把 A[l],A[l+1],…,A[r] 都加上 d. 2.“Q l r”,表示询问 A[l],A[l ...
- AcWing 247. 亚特兰蒂斯 (线段树,扫描线,离散化)
题意:给你\(n\)个矩形,求矩形并的面积. 题解:我们建立坐标轴,然后可以对矩形的横坐标进行排序,之后可以遍历这些横坐标,这个过程可以想像成是一条线从左往右扫过x坐标轴,假如这条线是第一次扫过矩形的 ...
随机推荐
- Websocket 突破最大长连接
为了测试机器能够最大的长连接个数,故写了一个js脚本,需要用node进行执行 var WebSocketClient = require('websocket').client; var size = ...
- 我的python学习之旅——安装python
windows下载安装: 1.下载安装包: 访问官方网站:https://www.python.org/downloads/ 下载自己想要的版本安装,这里下载当前最新版3.8: 选择64位的Windo ...
- poj2226-Muddy Fields二分匹配 最小顶点覆盖 好题
题目 给到一个矩阵,有些格子上是草,有些是水.需要用宽度为1,长度任意的若干块木板覆盖所有的水,并不能覆盖草,木板可以交叉,但只能横竖放置,问最少要多少块板. 分析 经典的矩阵二分图构图和最小点覆盖. ...
- Antdesign Form 实现页面控件的赋值加载
使用Antdesign Form时,当页面加载时,需要从后台获取数据,对Form中控件的默认赋值.看似比较简单的需求,而且Antdesign 官方文档中也有相应介绍,然后对于Form 的CheckBo ...
- Css几个兼容性问题
1.BUG_fireFox!!!一个容器内的子容器如果要左右浮动的话,需要在这个容器设置上样式:"overflow:hidden". 注:内部元素浮动就会导致外面的容器的高度在fi ...
- Dubbo从入门到实战视频教程
Dubbo是阿里巴巴公司开源的一个高性能优秀的服务框架,使得应用可通过高性能的 RPC 实现服务的输出和输入功能,可以和 Spring框架无缝集成.这里整理了一套关于dubbo的视频教程分享给大家,包 ...
- eclipses配置tomcat
1,项目右键属性,设置为1.8,与jdk相对应 2,自动发布,tomcat 3,使用自己的tomcat 4,
- 【转载】java工程师学习之路---给自己的目标
想学习或者提升java的可以看看,单从java角度来看总结的虽然还是很全面的,主要是为了自己看 http://blog.csdn.net/peace1213/article/details/50849 ...
- Windows Electron初探
最近闲来无事,玩玩electron. 1.安装nodejs 下载地址:http://nodejs.cn/download/,下载64位.安装完成后,打开C:\Program Files\nodejs\ ...
- openstack mitaka开启三层网络vxlan
在这之前,先把之前基于flat模式创建的虚机,全部删除 控制节点: 配置 修改/etc/neutron/neutron.conf的[DEFAULT]区域 将 core_plugin = ml2 ser ...