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第六周课堂示例总结
一.如果一个类中既有初始化块,又有构造方法,同时还设定了字段的初始值,谁说了算? public class InitializeBlockDemo { /** * @param args */ pub ...
- [Codeforces 266E]More Queries to Array...(线段树+二项式定理)
[Codeforces 266E]More Queries to Array...(线段树+二项式定理) 题面 维护一个长度为\(n\)的序列\(a\),\(m\)个操作 区间赋值为\(x\) 查询\ ...
- CVE-2018-19985漏洞学习
简介 4.19.8之前,在Linux内核中,hso_probe()函数中发现了一个缺陷,该函数从USB设备(作为u8)读取if_num值,并且不需要对数组进行长度检查就使用它来索引数组,从而导致在hs ...
- Linux服务器Java进程突然消失排查办法
出处:JAVA进程突然消失的原因? 问题描述 在实际生产环境下,如果我们遇见Java进程突然消失,该如何去排查问题? 思路 可能有几种原因: ①.Java应用程序的问题:发生OOM导致进程Crash ...
- luogu题解 P1707 【刷题比赛】矩阵加速递推
题目链接: https://www.luogu.org/problemnew/show/P1707 分析: 洛谷的一道原创题,对于练习矩阵加速递推非常不错. 首先我们看一下递推式: \(a[k+2]= ...
- Mac下的Web性能压力测试工具:ab(ApacheBench)
Web开发,少不了的就是压力测试,它是评估一个产品是否合格上线的基本标准. ab是一种用于测试Apache超文本传输协议(HTTP)服务器的工具.apache自带ab工具,可以测试Apache.IIS ...
- jQuery 遍历 - 祖先
通过 jQuery,您能够向上遍历 DOM 树,以查找元素的祖先. 向上遍历 DOM 树 这些 jQuery 方法很有用,它们用于向上遍历 DOM 树: parent() parents() pare ...
- 测试Random类nextInt()方法连续两次结果一样的概率
public static void main(String[] args) { int count = 0; int a = 0; Random r = new Random(); while (t ...
- 2019-2020-1 20199319《Linux内核原理与分析》第五周作业
系统调用的三层机制(上) 基础知识 1.通过库函数的方式进行系统调用,库函数用来把系统调用给封装起来. 2.CPU有四种不同的执行级别:0.1.2.3,数字越小,特权越高.Linux操作系统中采用了0 ...
- linux 静态路由
用ip route删除默认路由 ip route del default via 192.168.18.1 用route删除默认路由route del default gw 192.168.18.1 ...