http://acm.uestc.edu.cn/#/problem/show/844

程序设计竞赛

Time Limit: 3000/1000MS (Java/Others)     Memory Limit: 65535/65535KB (Java/Others)
Submit Status

“你动规无力,图论不稳,数据结构松散,贪心迟钝,没一样像样的,就你还想和我同台竞技,做你的美梦!今天这场比赛,就是要让你知道你是多么的无能!!”

不训练,无以为战。有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
1 2 3 4
0 1 3
1 3 -3
0 2 4
0 3 3
6
4
-3

思路:

每个节点维护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-程序设计竞赛 (线段树的区间最大连续和)【线段树】的更多相关文章

  1. 2018中国大学生程序设计竞赛 - 网络选拔赛 1010 YJJ's Salesman 【离散化+树状数组维护区间最大值】

    题目传送门:http://acm.hdu.edu.cn/showproblem.php?pid=6447 YJJ's Salesman Time Limit: 4000/2000 MS (Java/O ...

  2. ZZNU-OJ-2098 : Drink coffee【线段树合并区间或者 差分 + 二分索引树】

    : Drink coffee 时间限制: Sec 内存限制: MiB 提交: 答案正确: 提交 状态 讨论区 题目描述 为了在上课时保持清醒,凯伦需要一些咖啡.咖啡爱好者凯伦想知道最佳的温度来冲煮完美 ...

  3. HDU 6464 免费送气球 【权值线段树】(广东工业大学第十四届程序设计竞赛)

    传送门:http://acm.hdu.edu.cn/showproblem.php?pid=6464 免费送气球 Time Limit: 2000/1000 MS (Java/Others)    M ...

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

  5. 2016年湖南省第十二届大学生计算机程序设计竞赛---Parenthesis(线段树求区间最值)

    原题链接 http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1809 Description Bobo has a balanced parenthes ...

  6. HDU 6464.免费送气球-动态开点-权值线段树(序列中第first小至第second小的数值之和)(感觉就是只有一个状态的主席树) (“字节跳动-文远知行杯”广东工业大学第十四届程序设计竞赛)

    免费送气球 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submi ...

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

  8. 【线段树】hihocoder 1586 ACM-ICPC国际大学生程序设计竞赛北京赛区(2017)网络赛 I. Minimum

    题意:给你一个序列(长度不超过2^17),支持两种操作:单点修改:询问区间中最小的ai*aj是多少(i可以等于j). 只需要线段树维护区间最小值和最大值,如果最小值大于等于0,那答案就是minv*mi ...

  9. 吉首大学2019年程序设计竞赛(重现赛)-K(线段树)

    题目链接:https://ac.nowcoder.com/acm/contest/992/K 题意:给一个大小为1e5的数组,由0 1组成,有两种操作,包括区间修改,将一段区间内的0换成1,1换成0; ...

随机推荐

  1. java判断字符串中是否含有中文

    /** * 判断字符串中是否含有中文 */ public static boolean isCNChar(String s){ boolean booleanValue = false; for(in ...

  2. display:inline block inline-block 的区别

    原文地址:http://blog.csdn.net/jly036/article/details/5506182 display:block就是将元素显示为块级元素. block元素的特点是: 总是在 ...

  3. LDA-MySql

    http://blog.csdn.net/white_smile/article/details/19565701

  4. 1006 Sign In and Sign Out (25 分)

    1006 Sign In and Sign Out (25 分) At the beginning of every day, the first person who signs in the co ...

  5. 搭建OpenStack先电云平台

    实际操作示意图 在VMware里面创建两台centos7的虚拟机作为搭建云平台的两节点配置如下: 1.第一台虚拟机   作为控制节点 2CPU 3G以上内存 硬盘50G 网络适配器一个nat 一个仅主 ...

  6. RBAC相关的配置

    一.什么是RBAC 基于角色的访问控制(Role-Based Access Control)作为传统访问控制(自主访问,强制访问)的有前景的代替受到广泛的关注. 在RBAC中,权限与角色相关联,用户通 ...

  7. freePBX汉化方法记录——备忘

    FreePBX汉化[root@bgcc69:/var/www/html/admin/i18n/zh_CN/LC_MESSAGES]$pwd/var/www/html/admin/i18n/zh_CN/ ...

  8. 洛谷::P1972 [SDOI2009]HH的项链

    题目背景 无 题目描述 HH 有一串由各种漂亮的贝壳组成的项链.HH 相信不同的贝壳会带来好运,所以每次散步完后,他都会随意取出一段贝壳,思考它们所表达的含义.HH 不断地收集新的贝壳,因此,他的项链 ...

  9. Python之模块(二)

    1.subprocess模块 2.loggin模块 很多程序都有记录日志的需求,并且日志中包含的信息即有正常的程序访问日志,还可能有错误.警告等信息输出,python的logging模块提供了标准的日 ...

  10. php内存回收机制的学习

    今天朋友去面试,回来问了一下怎么样,结果他说一脸懵逼,看来我们平时还是学习的太少了啊.于是比较好奇,果断问了一下都有哪些问题,朋友说第一个问题就是“描述PHP的垃圾回收机制”,我当时听了也是一脸茫然, ...