cdoj844-程序设计竞赛 (线段树的区间最大连续和)【线段树】
http://acm.uestc.edu.cn/#/problem/show/844
程序设计竞赛
Time Limit: 3000/1000MS (Java/Others) Memory Limit: 65535/65535KB (Java/Others)
“你动规无力,图论不稳,数据结构松散,贪心迟钝,没一样像样的,就你还想和我同台竞技,做你的美梦!今天这场比赛,就是要让你知道你是多么的无能!!”
不训练,无以为战。有n项能力是ACM
竞赛要求的,训练则能提升,忽略则会荒废。
这m天,你能做到如何。
Input
第一行两个整数n,m,分别表示有n项能力要求,共有m天。
第二行n个整数,第i个整数ai表示第i项能力的数值。
接下来m行,每行开始先读入一个整数si,表明这是一次询问还是一次能力变化。
si=0,表明这是一次询问,然后读入两个整数li,ri,表示询问在[li,ri]区间中任选一段连续序列,这段序列中所有能力值之和最大能是多少。
si=1,表明这是一次能力变化,然后读入两个整数xi,wi,表示第xi项能力变为了wi。
1≤n,m≤100000,−10000≤ai≤10000,1≤li≤ri≤n,1≤xi≤n,−10000≤wi≤10000
Output
有多少询问就输出多少行,每行输出一个整数,作为对该询问的回答。
Sample input and output
Sample Input | Sample Output |
---|---|
4 4 |
6 |
思路:
每个节点维护4个值:
summ:此区间内的最大连续和
sum_:该节点以下的节点值得总和
suml:此区间的从左端开始的最大连续和
sumr:此区间的从右端开始的最大连续和
合并区间时,该区间的最大连续和为:max(左子节点的最大连续和,右子节点的最大连续和,左子节点的最大右连续和+右子节点的最大左连续和)
查询时返回一个整节点。因为每次要查询左子节点和右子节点,并且要比较它们的右连续最大和和左连续最大和,所以需要返回整个节点以便求值。
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm> using namespace std; #define INF 0x7fffffff
const int N=;
int n,m,a[N];
struct node
{
int left,right;
int sum_,summ,suml,sumr;
}tree[*N]; void build(int id,int l,int r);//建一棵线段树
node query_sum(int id,int l,int r);//查询区间和
void update(int id,int pos,int val);//更新位置pos的值 int main()
{
//freopen("D:\\input.in","r",stdin);
//freopen("D:\\output.out","w",stdout);
int bo,t1,t2;
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++)
scanf("%d",&a[i]);
build(,,n);
for(int i=;i<=m;i++)
{
scanf("%d%d%d",&bo,&t1,&t2);
if(bo)
update(,t1,t2);
else{
node tmp=query_sum(,t1,t2);
printf("%d\n",tmp.summ);
}
}
return ;
}
void build(int id,int l,int r)
{
tree[id].left=l;
tree[id].right=r;
if(l==r)
{
tree[id].sum_=a[l];
tree[id].summ=a[l];
tree[id].suml=a[l];
tree[id].sumr=a[l];
}
else
{
int mid=(l+r)/;
build(*id,l,mid);
build(*id+,mid+,r);
tree[id].sum_=tree[*id].sum_+tree[*id+].sum_;
tree[id].summ=max(max(tree[*id].summ,tree[*id+].summ),(tree[*id].sumr+tree[*id+].suml));
tree[id].suml=max(tree[*id].suml,tree[*id].sum_+tree[*id+].suml);
tree[id].sumr=max(tree[*id+].sumr,tree[*id].sumr+tree[*id+].sum_);
}
}
node query_sum(int id,int l,int r)
{
if(tree[id].left==l&&tree[id].right==r)
return tree[id];
else
{
node tmp,k1,k2;
int flag1=,flag2=;
int mid=(tree[id].left+tree[id].right)/;
if(r<=mid) return query_sum(*id,l,r);
if(l>mid) return query_sum(*id+,l,r);
if(l<=mid){
k1=query_sum(*id,l,mid);
flag1=;
}
if(r>mid){
k2=query_sum(*id+,mid+,r);
flag2=;
}
if(flag1&flag2){
tmp.sum_=k1.sum_+k2.sum_;
tmp.suml=max(k1.suml,k1.sum_+k2.suml);
tmp.sumr=max(k2.sumr,k1.sumr+k2.sum_);
tmp.summ=max(max(k1.summ,k2.summ),k1.sumr+k2.suml);
}else{
if(flag1) tmp=k1;
else tmp=k2;
}
return tmp;
}
}
void update(int id,int pos,int val)
{
if(tree[id].left==tree[id].right)
{
tree[id].sum_=val;
tree[id].summ=val;
tree[id].suml=val;
tree[id].sumr=val;
}
else
{
int mid=(tree[id].left+tree[id].right)/;
if(pos<=mid) update(*id,pos,val);
else update(*id+,pos,val);
tree[id].sum_=tree[*id].sum_+tree[*id+].sum_;
tree[id].summ=max(max(tree[*id].summ,tree[*id+].summ),(tree[*id].sumr+tree[*id+].suml));
tree[id].suml=max(tree[*id].suml,tree[*id].sum_+tree[*id+].suml);
tree[id].sumr=max(tree[*id+].sumr,tree[*id].sumr+tree[*id+].sum_);
}
}
cdoj844-程序设计竞赛 (线段树的区间最大连续和)【线段树】的更多相关文章
- 2018中国大学生程序设计竞赛 - 网络选拔赛 1010 YJJ's Salesman 【离散化+树状数组维护区间最大值】
题目传送门:http://acm.hdu.edu.cn/showproblem.php?pid=6447 YJJ's Salesman Time Limit: 4000/2000 MS (Java/O ...
- ZZNU-OJ-2098 : Drink coffee【线段树合并区间或者 差分 + 二分索引树】
: Drink coffee 时间限制: Sec 内存限制: MiB 提交: 答案正确: 提交 状态 讨论区 题目描述 为了在上课时保持清醒,凯伦需要一些咖啡.咖啡爱好者凯伦想知道最佳的温度来冲煮完美 ...
- HDU 6464 免费送气球 【权值线段树】(广东工业大学第十四届程序设计竞赛)
传送门:http://acm.hdu.edu.cn/showproblem.php?pid=6464 免费送气球 Time Limit: 2000/1000 MS (Java/Others) M ...
- 2016中国大学生程序设计竞赛 - 网络选拔赛 C. Magic boy Bi Luo with his excited tree
Magic boy Bi Luo with his excited tree Problem Description Bi Luo is a magic boy, he also has a migi ...
- 2016年湖南省第十二届大学生计算机程序设计竞赛---Parenthesis(线段树求区间最值)
原题链接 http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1809 Description Bobo has a balanced parenthes ...
- HDU 6464.免费送气球-动态开点-权值线段树(序列中第first小至第second小的数值之和)(感觉就是只有一个状态的主席树) (“字节跳动-文远知行杯”广东工业大学第十四届程序设计竞赛)
免费送气球 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Submi ...
- fzu 2105 Digits Count ( 线段树 ) from 第三届福建省大学生程序设计竞赛
http://acm.fzu.edu.cn/problem.php?pid=2105 Problem Description Given N integers A={A[0],A[1],...,A[N ...
- 【线段树】hihocoder 1586 ACM-ICPC国际大学生程序设计竞赛北京赛区(2017)网络赛 I. Minimum
题意:给你一个序列(长度不超过2^17),支持两种操作:单点修改:询问区间中最小的ai*aj是多少(i可以等于j). 只需要线段树维护区间最小值和最大值,如果最小值大于等于0,那答案就是minv*mi ...
- 吉首大学2019年程序设计竞赛(重现赛)-K(线段树)
题目链接:https://ac.nowcoder.com/acm/contest/992/K 题意:给一个大小为1e5的数组,由0 1组成,有两种操作,包括区间修改,将一段区间内的0换成1,1换成0; ...
随机推荐
- python学习笔记--pycurl模块安装遇到的问题。
1.用easy_install安装的时候 [root@idayuan ~]# easy_install pycurl Searching for pycurl Best match: pycurl A ...
- ES之七:配置文件详解
安装流程 http://www.elasticsearch.org/overview/elkdownloads/下载对应系统的安装包(我下载的是tar的),下载解压以后运行es根目录下bin目录的el ...
- R语言学习——欧拉计划(11)Largest product in a grid
Problem 11 In the 20×20 grid below, four numbers along a diagonal line have been marked in red. 08 0 ...
- var abc = function(x){} 和 function abc(x){}的区别
转自百度知道. 问:js里声明函数有几种方式? var abc = function(x){} 和 function abc(x){} 这两种声明方法有什么不同? 答:首先后者是指函数声明,前者是指函 ...
- [UE4]C++ 动态内存分配(6种情况,好几个例子)
1.堆内存分配 : C/C++定义了4个内存区间: 代码区,全局变量与静态变量区,局部变量区即栈区,动态存储区,即堆(heap)区或自由存储区(free store). 堆的概念: 通常定义变量(或对 ...
- linux(CentOS)安装phpstorm
例子一. 1.将其解压 2.用终端打开其文件 3.移动文件 sudo mv PhpStorm /opt/ (移动成功) 4.进入有移动后的目录 cd /opt/PhpStorm 5.进入bin目录执行 ...
- KCP 传输协议
作者:韦易笑链接:https://www.zhihu.com/question/36258781/answer/98944369来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明 ...
- SpringBoot入门篇--Thymeleaf引擎模板的基本使用方法
我们在使用SpringBoot框架的时候在前面已经介绍了Thymelea引擎模板,因为SpringBoot对JSP惨不忍睹的支持.那我们在使用引擎模板对前端页面进行渲染能够返回的情况下我们怎么才能在静 ...
- 求m-n之间数字的和
unction sum(m,n){ var sum = 0; if(m>n){ for(var i=n; i<=m; i++ ...
- extends和implements区别
extends与implements的不同 1.在类的声明中,通过关键字extends来创建一个类的子类. 一个类通过关键字implements声明自己使用一个或者多个接口. extends 是继承某 ...