POJ.2750.Potted Flower(线段树 最大环状子段和)
/*
13904K 532ms
最大 环状 子段和有两种情况,比如对于a1,a2,a3,a4,a5
一是两个端点都取,如a4,a5,a1,a2,那就是所有数的和减去不选的,即可以计算总和减最小连续子段和
二是两个端点不都取,如a1,a2,a3,那需要记录最大连续子段和
线段树,令maxs[l,r]为[l,r]上最大连续子段和,mins[l,r]同理
在向上更新时,可能是由整个左右节点拼成,也可能是只由左或右更新,也可能两段都有,但不包括最左/右端点
所以还需要记录包括区间左端点的maxsl,minsl,包括区间右端点的maxsr,minsr
那PushUp的转移就很好写了。见PushUp
是要求最大真子段和,不能包括所有点,要特判!
*/
#include<cstdio>
#include<cctype>
#include<algorithm>
//#define gc() getchar()
#define gc() (SS==TT &&(TT=(SS=IN)+fread(IN,1,MAXIN,stdin),SS==TT)?EOF:*SS++)
#define lson node[rt].ls
#define rson node[rt].rs
const int N=2e5+5,MAXIN=5e6;
int n;
char IN[MAXIN],*SS=IN,*TT=IN;
inline int read()
{
int now=0,f=1;register char c=gc();
for(;!isdigit(c);c=gc()) if(c=='-') f=-1;
for(;isdigit(c);now=now*10+c-'0',c=gc());
return now*f;
}
struct Seg_Tree
{
int tot;
struct Node
{
int l,r,ls,rs,sum,maxs,mins,maxsl,maxsr,minsl,minsr;
void Set(int v)
{
sum=maxs=mins=maxsl=maxsr=minsl=minsr=v;
}
}node[N<<1];
inline void PushUp(int rt)
{
node[rt].sum=node[lson].sum+node[rson].sum;
node[rt].maxs=std::max(std::max(node[lson].maxs,node[rson].maxs),node[lson].maxsr+node[rson].maxsl);
node[rt].mins=std::min(std::min(node[lson].mins,node[rson].mins),node[lson].minsr+node[rson].minsl);
node[rt].maxsl=std::max(node[lson].maxsl,node[lson].sum+node[rson].maxsl);
node[rt].minsl=std::min(node[lson].minsl,node[lson].sum+node[rson].minsl);
node[rt].maxsr=std::max(node[rson].maxsr,node[rson].sum+node[lson].maxsr);
node[rt].minsr=std::min(node[rson].minsr,node[rson].sum+node[lson].minsr);
}
void Build(int l,int r)
{
int p=tot++;
node[p].l=l, node[p].r=r;
if(l==r)
{
node[p].ls=node[p].rs=-1;
node[p].Set(read());
// node[p].sum=node[p].maxs=node[p].mins=node[p].maxsl=node[p].minsl=node[p].maxsr=node[p].minsr=read();
return;
}
int m=l+r>>1;
node[p].ls=tot, Build(l,m);
node[p].rs=tot, Build(m+1,r);
PushUp(p);
}
void Modify(int rt,int pos,int v)
{
if(node[rt].l==node[rt].r){node[rt].Set(v); return;}
int m=node[rt].l+node[rt].r>>1;
if(pos<=m) Modify(lson,pos,v);
else Modify(rson,pos,v);
PushUp(rt);
}
// int Query_Max(int rt,int L,int R)
// {
// if(L<=node[rt].l && node[rt].r<=R) return node[rt].maxs;
// int m=node[rt].l+node[rt].r>>1;
// if(L<=m)
// if(m<R) return std::max(Query_Max(lson,L,R),Query_Max(rson,L,R));
// else Query_Max(lson,L,R);
// return Query_Max(rson,L,R);
// }
// int Query_Min(int rt,int L,int R)
// {
// if(L<=node[rt].l && node[rt].r<=R) return node[rt].mins;
// int m=node[rt].l+node[rt].r>>1;
// if(L<=m)
// if(m<R) return std::min(Query_Min(lson,L,R),Query_Min(rson,L,R));
// else Query_Min(lson,L,R);
// return Query_Min(rson,L,R);
// }
}t;
int main()
{
#ifndef ONLINE_JUDGE
freopen("2750.in","r",stdin);
#endif
n=read();
t.Build(1,n);
int m=read(),p,v;
while(m--)
p=read(),v=read(),t.Modify(0,p,v),
printf("%d\n",t.node[0].sum==t.node[0].maxs? t.node[0].sum-t.node[0].mins : std::max(t.node[0].maxs,t.node[0].sum-t.node[0].mins));//全是正数则要减去一个最小值
// printf("%d\n",std::max(t.Query_Max(0,1,n),t.node[0].sum-t.Query_Min(0,1,n)));
// printf("Max:%d Min:%d sum:%d\n",t.Query_Max(0,1,n),t.Query_Min(0,1,n),t.node[0].sum);
return 0;
}
POJ.2750.Potted Flower(线段树 最大环状子段和)的更多相关文章
- POJ 2750 Potted Flower (线段树区间合并)
开始懵逼找不到解法,看了网上大牛们的题解才发现是区间合并... 给你n个数形成一个数列环,然后每次进行一个点的修改,并输出这个数列的最大区间和(注意是环,并且区间最大只有n-1个数) 其实只需要维护 ...
- POJ 2750 Potted Flower(线段树+dp)
题目链接 虽然是看的别的人思路,但是做出来还是挺高兴的. 首先求环上最大字段和,而且不能是含有全部元素.本来我的想法是n个元素变为2*n个元素那样做的,这样并不好弄.实际可以求出最小值,总和-最小,就 ...
- (简单) POJ 2750 Potted Flower,环+线段树。
Description The little cat takes over the management of a new park. There is a large circular statue ...
- POJ 2750 Potted Flower(线段树的区间合并)
点我看题目链接 题意 : 很多花盆组成的圆圈,每个花盆都有一个值,给你两个数a,b代表a位置原来的数换成b,然后让你从圈里找出连续的各花盆之和,要求最大的. 思路 :这个题比较那啥,差不多可以用DP的 ...
- POJ 2750 Potted Flower
Potted Flower Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 3872 Accepted: 1446 Des ...
- POJ 2750 Potted Flower (单点改动求线段树上最大子序列和)
题目大意: 在一个序列上每次改动一个值,然后求出它的最大的子序列和. 思路分析: 首先我们不考虑不成环的问题.那就是直接求每一个区间的最大值就好了. 可是此处成环,那么看一下以下例子. 5 1 -2 ...
- Potted Flower(线段树+dp)
http://poj.org/problem?id=2750 题意:在一个圈中取若干个相邻的数,求他们的最大序列和.不能够同时取所有的数. 看了一篇解题报告写的很详细..http://blog.csd ...
- HDU 1828 / POJ 1177 Picture (线段树扫描线,求矩阵并的周长,经典题)
做这道题之前,建议先做POJ 1151 Atlantis,经典的扫描线求矩阵的面积并 参考连接: http://www.cnblogs.com/scau20110726/archive/2013/0 ...
- poj 3277 City Horizon (线段树 扫描线 矩形面积并)
题目链接 题意: 给一些矩形,给出长和高,其中长是用区间的形式给出的,有些区间有重叠,最后求所有矩形的面积. 分析: 给的区间的范围很大,所以需要离散化,还需要把y坐标去重,不过我试了一下不去重 也不 ...
随机推荐
- 使用密钥认证机制远程登录Linux
密钥认证机制 创建存放key的文件 1)创建目录 /root/.ssh 并设置权限 [root@localhost ~]# mkdir /root/.ssh mkdir 命令用来创建目录,以后会详细介 ...
- UML和模式应用4:初始阶段(3)--需求制品之用例模型
1. 前言 UP开发包括四个阶段:初始阶段.细化阶段.构建阶段.移交阶段: UP每个阶段包括 业务建模.需求.设计等科目: 其中需求科目对应的需求制品包括:设想.业务规则.用例模型.补充性规格说明.词 ...
- scp -r拷贝目录不会拷贝软连接
scp -r拷贝目录,不会拷贝 软连接的 解决方法: 使用rsync拷贝 参考:rsync本地及远程复制备份[原创] - paul_hch - 博客园 https://www.cnblogs.com/ ...
- HTML学习笔记03-HTML基础
<!DOCTYPE HTML> <html> <head> <title> </title> </head> <body& ...
- 量化投资与Python之NumPy
数组计算 NumPy是高性能科学计算和数据分析的基础包.它是pandas等其他各种工具的基础.NumPy的主要功能:ndarray,一个多维数组结构,高效且节省空间无需循环对整组数据进行快速运算的 ...
- .NET CORE 1.1 迁移到.NET 2.0正式版
以下操作参考官方文档 1:首先你需要升级到最新版的VS 2017 15.3 升级的地方在VS右上角有个黄色的更新提醒,如果没有请挂VPN或者重新下载一个新的. 2:第二步 和之前改.NET Frame ...
- centos6.5下系统编译定制iptables防火墙扩展layer7应用层访问控制功能及应用限制QQ2016上网
iptables防火墙扩展之layer7应用层访问控制 概述: iptables防火墙是工作在网络层,针对TCP/IP数据包实施过滤和限制,属于典型的包过滤防火墙.以基于网络层的数据包过滤机制为主,同 ...
- javascript NaN注意事项
NaN直译是Not a number NaN是个特殊的number,它和任何值相比都不相等,甚至和它自己. NaN === NaN 这个表达式是false 唯一能判断NaN的方法是 IsNaN(NaN ...
- JavaScript对象之深度克隆
也不知道从什么时候开始,前端圈冒出了个新词:对象深度克隆.看起来好像很高大上的样子,实际上并不新鲜,在我们的实际项目开发中,你可能早已用到,只不过由于汉字的博大精深,有些原本很简单的事物被一些看似专业 ...
- 并发之atomicInteger与CAS机制
并发之atomic与CAS自旋锁 通过前几章的讲解我们知道i++这种类似操作是不安全的.针对这种情况,我们可能会想到利用synchronize关键字实现线程同步,保证++操作的原子性,的确这是一种有效 ...