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坐标轴,假如这条线是第一次扫过矩形的 ...
随机推荐
- JAVA基础--JAVA API常见对象(字符串&缓冲区)
一. String 类型 1. String类引入 第二天学习过Java中的常量: 常量的分类: 数值型常量:整数,小数(浮点数) 字符型常量:使用单引号引用的数据 字符串常量:使用双引号引用 ...
- Junit+Mock单元测试
项目用的是maven,所需jar包在pom.xml文件里面配置,单元测试要用的jar具体如下: <dependency> <groupId>junit</groupId& ...
- AcWing175电路维修
这是一道在luogu的蓝题,在yxc大佬的讲解下AC掉了(百般调试) 首先这道题给了一个字符串矩阵,/ \表示相连哪两个节点,只可以走/ \所连接的两个点,但我们可以旋转每一个边,询问从1,1 走到 ...
- Dedesql数据库类详解(二次开发必备教程)
其实数据库类织梦之前就有一个介绍,http://help.dedecms.com/v53/archives/functions/db/,这篇文章讲解了数据库类的一些常见的使用方法,不过没有结合例子去介 ...
- 手写一个python迭代器
分析 我们都知道一个可迭代对象可以通过iter()可以返回一个迭代器. 如果想要一个对象称为可迭代对象,即可以使用for,那么必须实现__iter __()方法. 在一个类的实例对象想要变成迭代器,就 ...
- CSS(下)
目录 CSS(下) CSS属性相关 宽和高 字体属性 背景属性 边框 border-radius display属性 CSS盒子模型 margin外边距 padding内填充 浮动(float) 限制 ...
- 单个html5页面加个密码访问
单个html5页面要实现加个密码才能访问,可以用js来控制.代码加在<head>插入下面代码</head>代码如下: <script languange="Ja ...
- CentOS 7 防火墙常用操作及常见问题处理
一.常用操作 1.启动防火墙: systemctl start firewalld.service 2.关闭防火墙: systemctl stop firewalld.service 3.添加放行端口 ...
- linux无界面模式安装selenium+chrome+chromedriver并成功完成脚本(亲测可用)
环境:docker centos 7.4 能通外网 写好的selenium脚本. 具体步骤: 一:安装selenium 这是最简单的 直接利用 pip3 install selenium 二 安装c ...
- 2019.9.25使用BP和Hydra爆破相关的服务
使用BP和Hydra爆破相关的服务. Hydra:九头蛇,开源的功能强大的爆破工具,支持的服务有很多,使用hydra爆破c/s架构的服务.使用bp爆破web登录端口. dvwa:web应用程序漏洞演练 ...