给定长度为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. 你能回答这些问题吗(线段树最大子段和)的更多相关文章

  1. Acwing 245.你能回答这些问题吗

    题目描述 给定长度为N的数列A,以及M条指令,每条指令可能是以下两种之一: 1."1 x y",查询区间 [x,y] 中的最大连续子段和,即 maxx≤l≤r≤y{∑ri=lA[i ...

  2. ACwing 你能回答这些问题吗(线段树求最大连续字段和)

    给定长度为N的数列A,以及M条指令,每条指令可能是以下两种之一: 1.“1 x y”,查询区间 [x,y] 中的最大连续子段和,即 maxx≤l≤r≤ymaxx≤l≤r≤y{∑ri=lA[i]∑i=l ...

  3. acwing 243. 一个简单的整数问题2 树状数组 线段树

    地址 https://www.acwing.com/problem/content/description/244/ 给定一个长度为N的数列A,以及M条指令,每条指令可能是以下两种之一: 1.“C l ...

  4. AcWing 243. 一个简单的整数问题2 (树状数组)打卡

    题目:https://www.acwing.com/problem/content/244/ 题意:区间加,区间查询 思路:我们把原先那个差分数组分解一下 ∑i=1x∑j=1ib[j]=∑i=1x(x ...

  5. AcWing:242. 一个简单的整数问题(树状数组)

    给定长度为N的数列A,然后输入M行操作指令. 第一类指令形如“C l r d”,表示把数列中第l~r个数都加d. 第二类指令形如“Q X”,表示询问数列中第x个数的值. 对于每个询问,输出一个整数表示 ...

  6. AcWing:148. 合并果子(哈夫曼树)

    在一个果园里,达达已经将所有的果子打了下来,而且按果子的不同种类分成了不同的堆. 达达决定把所有的果子合成一堆. 每一次合并,达达可以把两堆果子合并到一起,消耗的体力等于两堆果子的重量之和. 可以看出 ...

  7. AcWing 107. 超快速排序(归并排序 + 逆序对 or 树状数组)

    在这个问题中,您必须分析特定的排序算法----超快速排序. 该算法通过交换两个相邻的序列元素来处理n个不同整数的序列,直到序列按升序排序. 对于输入序列9 1 0 5 4,超快速排序生成输出0 1 4 ...

  8. 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 ...

  9. AcWing 247. 亚特兰蒂斯 (线段树,扫描线,离散化)

    题意:给你\(n\)个矩形,求矩形并的面积. 题解:我们建立坐标轴,然后可以对矩形的横坐标进行排序,之后可以遍历这些横坐标,这个过程可以想像成是一条线从左往右扫过x坐标轴,假如这条线是第一次扫过矩形的 ...

随机推荐

  1. CF39H 【Multiplication Table】

    这题可以枚举出每个i,j 位置的数>需要用到进制转换 int zh(int x){ long long sum=0,i=0; while(x){ sum=sum+((x%n)*pow(10,i) ...

  2. 引入DDT

    一.大致介绍: DDT-Data Driven Test 是Python的第三方库,提供了创建数据驱动的测试,在线安装为:pip install ddt @data 表示元祖的列表数据 @unpack ...

  3. SG函数和SG定理(Sprague_Grundy)

    一.必胜点和必败点的概念 P点:必败点,换而言之,就是谁处于此位置,则在双方操作正确的情况下必败.       N点:必胜点,处于此情况下,双方操作均正确的情况下必胜. 必胜点和必败点的性质:     ...

  4. python网络爬虫(4)结构与基本概念

    基本模型 请求与响应 import urllib.request as urllib2 request=urllib2.Request('http://www.zhihu.com') response ...

  5. DIj

    using System;using System.Collections.Generic;using System.Linq;using System.Text; namespace DefineG ...

  6. 移动端实1px细线方法

    前言 在移动端中,宽度100%,1px的线看起来要比pc端中宽度100%,1px的线粗, 那是因为css中的1px并不等于移动设备(物理像素)的1px.物理像素显示是1个像素代表2个像素,所以出现为2 ...

  7. pycharm设置用滑轮改变字体大小

    在电脑第一次安装pycharm之后,发现每次调整代码界面的字体,总是需要到setting里面调整,这样非常不方便,特别是对于代码量很多的时候,我们有时候需要把目光聚焦到某一句代码,这个时候就需要放大, ...

  8. 03 python3常见内置函数

    数学相关 abs(a) : 求取绝对值.abs(-1) max(list) : 求取list最大值.max([1,2,3]) min(list) : 求取list最小值.min([1,2,3]) su ...

  9. SAP模块一句话入门(专业术语的理解)

    SAP模块一句话入门(专业术语的理解) SAP一句话入门:Financial & Controlling Accounting (FICO) 财务,财务,呵呵,让我们关心一下给我发工资的部门. ...

  10. call,apply,bind的理解

    call,apply,bind均是用于改变this指向. 三者相似之处: 1:都是用于改变函数的this指向. 2:第一个参数都是this要指向的对象. 3:都可以通过后面的参数进行对方法的传参. l ...