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; ...
随机推荐
- unittest框架断言方法
assertEqual(a, b) 判断a==b assertNotEqual(a, b) 判断a!=b assertTrue(x) bool( ...
- 操作系统-移动操作系统-百科: iOS(苹果公司的移动操作系统)
ylbtech-操作系统-移动操作系统-百科: iOS(苹果公司的移动操作系统) iOS是由苹果公司开发的移动操作系统.苹果公司最早于2007年1月9日的Macworld大会上公布这个系统,最初是设计 ...
- red hat官方的rhel操作系统版本号与内核版本号的对应关系
原文在如下网址:https://access.redhat.com/articles/3078 The tables below list the major and minor Red Hat En ...
- 绕过限制,在PC上调试微信手机页面
场景 假设一个手机页面,开发者对其做了限制,导致只能在微信客户端中打开.而众所周知手机上非常不利于调试页面,所以需要能在电脑上打开并进行调试.这里针对常见的三种页面做一下分析,一一绕过其限制,(当然不 ...
- html_常用技巧总结
============= 博客大全: 脚本之家:http://www.jb51.net/list/list_233_104.htm 红黑联盟: http://www.2cto.com/kf/yid ...
- VLC在web系统中应用(x-vlc-plugin 即如何把VLC嵌入HTML中)第一篇
VLC毫无疑问是优秀的一款播放软件,子B/S机构的web项目中,如果能把它嵌入页面,做页面预览或者其他,是非常棒的. 第一步:下载VLC安装程序:(推荐1.0.3或者是1.0.5版本,比较稳定) ht ...
- PHP mysqli_fetch_object() 函数实例讲解
定义和用法 mysqli_fetch_object() 函数从结果集中取得当前行,并作为对象返回. 注释:该函数返回的字段名是区分大小写的. 语法 mysqli_fetch_object(result ...
- ssh连接失败,提示 WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!
[root@iZ2ze4kh1rvftq4cevdfjwZ ~]# ssh IP @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ...
- 传统三层架构与DDD分层架构
参考 https://www.cnblogs.com/sandyliu1999/p/4969445.html
- Redis 在 LINUX 系统下 安装, 启动
01, 下载 http://www.redis.cn/ , 这里下再下来的是 redis-4.0.1.tar.gz 这个压缩包 02, 将压缩包放到 linux 系统中, 一般放在 usr/lo ...