Can you answer these queries III
2019-08-16 07:47:24来源:博客园 阅读 ()
Can you answer these queries III
Can you answer these queries III
题目:洛谷 SPOJ
【题目描述】
给定长度为N的数列A,以及M条指令,每条指令可能是以下两种之一:
1.“0 x y”,把A[x]改成y;
2.“1 x y”,查询区间[x,y]中的最大连续子段和。
【输入格式】
第一行,N;
第二行,N个数,即A[1]...A[N];
第三行,M;
第4至第M+3行,每行三个整数,分别表示“0或1”,x,y,即指令。
【输出格式】
i行,i表示“1 x y”的数量,每行1个整数,即指令2的答案。
【数据规模】
N,M<=50000。
解析
查询区间最大连续子段和,显然可以用线段树维护序列。
先分析一下,在线段树中,对于查询的每个区间[x,y],会有以下两种情况:
1、如图所示,区间刚好在一个子树中,只需查询该子树的区间最大连续子段和即可;
2、如图所示,区间一部分在左子树中,另一部分在右子树中,对于这种情况,该区间的最大连续子段和为左子树的最大后缀和加上右子树的最大前缀和。
考虑完所有情况后,只需套上线段树模板再稍作修改即可。
Code
#include <algorithm> #include <iostream> #include <cstring> #include <string> #include <cstdio> #include <cmath> #include <queue> using namespace std; struct rec{ int l,r,maxn,lmax,rmax,sum;//lmax最大前缀和,rmax最大后缀和 }t[200010]; int n,m,a[50001]; void build(int p,int l,int r) { t[p].l=l,t[p].r=r; if(l==r) { t[p].sum=t[p].lmax=t[p].rmax=t[p].maxn=a[l]; return ; } int mid=(l+r)/2; build(p*2,l,mid); build(p*2+1,mid+1,r); t[p].sum=t[p*2].sum+t[p*2+1].sum; t[p].lmax=max(t[p*2].lmax,t[p*2].sum+t[p*2+1].lmax); t[p].rmax=max(t[p*2+1].rmax,t[p*2+1].sum+t[p*2].rmax); t[p].maxn=max(t[p*2].rmax+t[p*2+1].lmax,max(t[p*2].maxn,t[p*2+1].maxn)); return ; } void change(int p,int x,int v) { if(t[p].l==t[p].r) { t[p].sum=t[p].rmax=t[p].lmax=t[p].maxn=v; return ; } int mid=(t[p].l+t[p].r)/2; if(x<=mid) change(p*2,x,v); else change(p*2+1,x,v); t[p].sum=t[p*2].sum+t[p*2+1].sum; t[p].lmax=max(t[p*2].lmax,t[p*2].sum+t[p*2+1].lmax); t[p].rmax=max(t[p*2+1].rmax,t[p*2+1].sum+t[p*2].rmax); t[p].maxn=max(t[p*2].rmax+t[p*2+1].lmax,max(t[p*2].maxn,t[p*2+1].maxn)); } rec ask(int p,int l,int r) { if(l<=t[p].l&&r>=t[p].r) return t[p]; rec a,b,ans; a.sum=a.lmax=a.rmax=a.maxn=b.sum=b.lmax=b.rmax=b.maxn=0xcfcfcfcf; ans.sum=0; int mid=(t[p].l+t[p].r)/2; if(l<=mid) { a=ask(p*2,l,r); ans.sum+=a.sum; } if(r>mid) { b=ask(p*2+1,l,r); ans.sum+=b.sum; } ans.maxn=max(max(a.maxn,b.maxn),a.rmax+b.lmax); //注意负数 ans.lmax=max(a.lmax,a.sum+b.lmax); ans.rmax=max(b.rmax,b.sum+a.rmax); if(l>mid) ans.lmax=max(ans.lmax,b.lmax); if(r<=mid) ans.rmax=max(ans.rmax,a.rmax); //分类讨论 return ans; } int main() { int c,l,r; cin>>n; for(int i=1;i<=n;i++) cin>>a[i]; build(1,1,n); cin>>m; for(int i=1;i<=m;i++) { cin>>c>>l>>r; if(c==0) change(1,l,r); else cout<<ask(1,l,r).maxn<<endl; } return 0; }View Code
原文链接:https://www.cnblogs.com/I-Love-You-520/p/11158831.html
如有疑问请与原作者联系
标签:
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有
上一篇:QT防止程序多次启动
- C++ non-const lvalue reference cannot bind to a temporar 2020-03-09
- 洛谷P1014 Cantor表 2020-02-06
- C/C++的几个输入流 2019-08-16
- 短语 2019-04-25
- Linux下QT、cannot find -lGL、 2019-01-21
IDC资讯: 主机资讯 注册资讯 托管资讯 vps资讯 网站建设
网站运营: 建站经验 策划盈利 搜索优化 网站推广 免费资源
网络编程: Asp.Net编程 Asp编程 Php编程 Xml编程 Access Mssql Mysql 其它
服务器技术: Web服务器 Ftp服务器 Mail服务器 Dns服务器 安全防护
软件技巧: 其它软件 Word Excel Powerpoint Ghost Vista QQ空间 QQ FlashGet 迅雷
网页制作: FrontPages Dreamweaver Javascript css photoshop fireworks Flash