UVa 1400(LA 3938)动态最大连续和
2015-12-05 00:37
393 查看
【题目链接】
http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=36216
【解题报告】
刘汝佳的《训练指南》里,我觉得这道题目讲的不够详细(并且书上貌似有一点印刷错误?)。
在网上找了很多题解,不过觉得代码写的很丑。直到我看到了这篇题解,觉得代码写的非常漂亮,就虚心学习了。
http://blog.csdn.net/u012997373/article/details/39609271
《UVA - 1400”Ray, Pass me the dishes!”(线段树) 》 –miss_minor
这道题目的算法本身并没有太多困难的令人感到棘手的地方,虽然是普通的线段树单点更新,区间查询,但实现起来,对我来说却非常有困难。原因在于数据的组织能力实在太弱。而这道题又恰恰由繁复的数据及其相应操作组织而成。
对于线段树的每个节点(这本身是一个类)要保存三个线段信息(注意这里又抽象出了一个类:线段),最大前缀,最大后缀,最大子序列。同时还要保存节点相对应的序列左端点和右端点。
对于每条线段,同样要保存左右节点,并且题目中有合并两条线段的操作,还有需要进行线段“优先级”的比较。
因此,如何在有限时间内写出结构清晰,层次完整,便于调试和扩展的代码,是十分考验编码能力的。
【参考代码】
http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=36216
【解题报告】
刘汝佳的《训练指南》里,我觉得这道题目讲的不够详细(并且书上貌似有一点印刷错误?)。
在网上找了很多题解,不过觉得代码写的很丑。直到我看到了这篇题解,觉得代码写的非常漂亮,就虚心学习了。
http://blog.csdn.net/u012997373/article/details/39609271
《UVA - 1400”Ray, Pass me the dishes!”(线段树) 》 –miss_minor
这道题目的算法本身并没有太多困难的令人感到棘手的地方,虽然是普通的线段树单点更新,区间查询,但实现起来,对我来说却非常有困难。原因在于数据的组织能力实在太弱。而这道题又恰恰由繁复的数据及其相应操作组织而成。
对于线段树的每个节点(这本身是一个类)要保存三个线段信息(注意这里又抽象出了一个类:线段),最大前缀,最大后缀,最大子序列。同时还要保存节点相对应的序列左端点和右端点。
对于每条线段,同样要保存左右节点,并且题目中有合并两条线段的操作,还有需要进行线段“优先级”的比较。
因此,如何在有限时间内写出结构清晰,层次完整,便于调试和扩展的代码,是十分考验编码能力的。
【参考代码】
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> using namespace std; const int maxn=500000+10; typedef long long LL; int A[maxn]; long long S[maxn]; int n,m; struct Segment { LL v; int l,r; Segment ( int l=0, int r=0, LL v=0 ) { this ->l=l; this ->r=r; this ->v=v; } Segment operator + ( const Segment& a )const { Segment ans; ans.l=min( l,a.l ); ans.r=max( r,a.r ); ans.v=v+a.v; return ans; } bool operator < ( const Segment& a )const { if( v==a.v ) { if( l==a.l ) { return r>a.r; } return l>a.l; } return v<a.v; } }; struct node { int l,r; Segment max_sub,max_pre,max_suf; void set( int l, int r, Segment max_sub, Segment max_pre, Segment max_suf ) { this->l=l; this->r=r; this->max_sub=max_sub; this->max_pre=max_pre; this->max_suf=max_suf; } }; node tree[maxn*4]; void build( int O, int L, int R ) { if( L>R )return; if( L==R ) { Segment temp( L,L,A[L] ); tree[O].set( L,R,temp,temp,temp ); return ; } int mid=L+(R-L)/2; build( O*2, L, mid ); build( O*2+1, mid+1,R ); Segment now_left( L,mid,S[mid]-S[L-1] ); Segment now_right( mid+1, R, S[R]-S[mid] ); tree[O].max_sub=max( tree[O*2].max_suf+tree[O*2+1].max_pre , max(tree[O*2].max_sub , tree[O*2+1].max_sub) ); tree[O].max_pre=max( tree[O*2].max_pre , now_left+tree[O*2+1].max_pre ); tree[O].max_suf=max( tree[O*2+1].max_suf, now_right+tree[O*2].max_suf ); tree[O].l=tree[O*2].l; tree[O].r=tree[O*2+1].r; } node query( int O, int qL, int qR ) { int L=tree[O].l,R=tree[O].r; int mid=(L+R)/2; // cout<<L<<" "<<R<<endl; if( qL<=L && R<=qR ) return tree[O]; if( qR<=mid )return query( O*2, qL, qR ); else if( qL>mid ) return query( O*2+1, qL, qR ); else //if( qR>=L && qL<=R ) { node nL=query( O*2, qL,qR ); node nR=query( O*2+1, qL, qR ); node ret; LL S_L=S[nL.r] - S[nL.l-1], S_R=S[nR.r]-S[nR.l-1]; Segment L_seg( L,mid,S_L ); Segment R_seg( mid+1, R, S_R ); ret.max_pre=max( nL.max_pre, L_seg+nR.max_pre ); ret.max_sub=max( max( nL.max_sub,nR.max_sub ), nL.max_suf+nR.max_pre ); ret.max_suf=max( nR.max_suf, R_seg+nL.max_suf ); ret.l=nL.l; ret.r=nR.r; return ret; } } int main( ) { int kase=0; while(~scanf( "%d%d", &n, &m )) { printf( "Case %d:\n",++kase ); for( int i=1; i<=n; i++ ) { scanf( "%d",&A[i] ); S[i]=S[i-1]+A[i]; } build( 1, 1, n ); for( int i=1; i<=m; i++ ) { int qL, qR; scanf("%d%d",&qL,&qR); node ans=query( 1, qL, qR ); printf( "%d %d\n", ans.max_sub.l, ans.max_sub.r ); // cout<<tree[1].max_sub.l<<" "<<tree[4].max_sub.r<<endl; } } return 0 ; }
相关文章推荐
- Android Retrofit 框架上传多张图片解决方案
- linux 信号发送函数sigqueue和信号安装函数sigaction用法
- JDK下载与配置
- ASP.NET 5 Configuration
- 解决Error: That port is already in use.
- nagios安装配置
- 关于左移和右移
- 用C++类实现简单的栈
- Tomcat ClassLoader机制
- iOS7以上图片模糊效果
- HDU5510(KMP)
- JAVA随堂笔记课【一】:命名规范
- SQL 查询横表变竖表
- HTML初级教程
- Pthreads并行编程之spin lock与mutex性能对比分析
- python核心编程-可变参数3
- 调整数组中奇数偶数位置
- POJ3461(KMP模板题)
- 各种算法的性质
- [1000]:A + B Problem