HDU 3016 线段树单点更新+DP
2015-12-15 01:58
447 查看
【题目链接】
http://acm.hdu.edu.cn/showproblem.php?pid=3016
【解题报告】
这道题目把线段树和DP结合起来了,所以并没有思路。参考了一篇题解,觉得讲的非常好:
http://www.cnblogs.com/scau20110726/archive/2013/05/11/3073398.html
–Titanium
这道题目的关键在于更新。
不加分析的给出算法:
线段树每个节点维护一个cover值表示它所对应的区间被cover值记录的线段所覆盖。如果没有被线段覆盖,cover值为-1.
从低到高往线段树里添加线段,每条线段先记录下他能到达的左边的比他低的线段的编号,右边的比他低的线段的编号,然后把这条线段加入线段树。
算法的正确性显而易见。从x点往下跳,如果可以跳到木板上,一定是某条木板(li,ri)覆盖了x点,离x点最近的,一定是最高的线段,所以高层线段覆盖低层线段是必须的。
之后跑一个DFS即可。
DFS的过程我漏讨论了一边可以直接掉到地板,一边可以掉到别的木板上的情况,wa了好几次TAT。
【参考代码】
http://acm.hdu.edu.cn/showproblem.php?pid=3016
【解题报告】
这道题目把线段树和DP结合起来了,所以并没有思路。参考了一篇题解,觉得讲的非常好:
http://www.cnblogs.com/scau20110726/archive/2013/05/11/3073398.html
–Titanium
这道题目的关键在于更新。
不加分析的给出算法:
线段树每个节点维护一个cover值表示它所对应的区间被cover值记录的线段所覆盖。如果没有被线段覆盖,cover值为-1.
从低到高往线段树里添加线段,每条线段先记录下他能到达的左边的比他低的线段的编号,右边的比他低的线段的编号,然后把这条线段加入线段树。
算法的正确性显而易见。从x点往下跳,如果可以跳到木板上,一定是某条木板(li,ri)覆盖了x点,离x点最近的,一定是最高的线段,所以高层线段覆盖低层线段是必须的。
之后跑一个DFS即可。
DFS的过程我漏讨论了一边可以直接掉到地板,一边可以掉到别的木板上的情况,wa了好几次TAT。
【参考代码】
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #define root 1,1,100000 using namespace std; const int INF=1e9; const int maxn=1e5+50; int N,ans; int cover[maxn*4],dp[maxn]; int Left[maxn],Right[maxn]; struct Type { int l,r,h,value; bool operator <( const Type& a ) const { return h<a.h; //h is dictinct } }; Type line[maxn]; void build( int O, int L, int R ) { if( L==R ) cover[O]=-1; else { int mid=(L+R)/2; build( O*2,L,mid ); build( O*2+1,mid+1,R ); cover[O]=-1; } } void pushdown( int O ) { if( cover[O]!=-1 ) { cover[O*2]=cover[O*2+1]=cover[O]; cover[O]=-1; } } void update( int O, int L, int R, int qL,int qR,int v ) { if( qL<=L && R<=qR ) cover[O]=v; else { pushdown( O ); int mid=(L+R)/2; if( qL<=mid )update( O*2, L, mid, qL, qR, v ); if( qR>mid )update( O*2+1, mid+1, R, qL, qR, v ); } } int query( int O, int L, int R, int x ) { if( L==R )return cover[O]; if( cover[O]!=-1 ) { if( L<=x && x<=R ) return cover[O]; } else { int mid=(L+R)/2; if( x<=mid )return query( O*2,L,mid,x ); else return query( O*2+1,mid+1,R,x ); } } void DFS( int pos ) { if( Left[pos]==-1 && Right[pos]==-1 ){ ans=max( ans,dp[pos] ); return; } if( Left[pos]!=-1 ) { dp[Left[pos]]=max( dp[Left[pos]], dp[pos]+ line[Left[pos]].value ) ; if( dp[Left[pos]]>0 ) DFS( Left[pos] ); } else { ans=max( ans,dp[pos] ); } if( Right[pos]!=-1 ) { dp[Right[pos]]=max( dp[Right[pos]], dp[pos]+line[Right[pos]].value); if( dp[Right[pos]]>0 ) DFS( Right[pos] ); } else { ans=max(ans,dp[pos]); } } int main() { while( ~scanf("%d",&N) ) { build( root ); for( int i=1; i<=N; i++ )scanf( "%d%d%d%d",&line[i].h,&line[i].l,&line[i].r,&line[i].value ); sort( line+1,line+1+N ); for( int i=1; i<=N; i++ ) { Left[i]=query( root,line[i].l ); Right[i]=query( root,line[i].r ); update( root, line[i].l, line[i].r, i ); } for( int i=1; i<=N; i++ ) dp[i]=-1*INF; dp =100+line .value; if( dp <=0 ) { printf("-1\n"); continue; } ans=-1*INF; DFS( N ); if( ans<=0 )printf( "-1\n" ); else printf("%d\n",ans); } return 0; } }
相关文章推荐
- 296. Best Meeting Point
- ORACLE LINUX 5.11 UDEV绑定asm磁盘问题
- UVALive 6905 Two Yachts(费用流)
- awk单行脚本快速参考
- UVALive 6904 Travel Card(dp)
- glsl计算sprite的亮度饱和度对比度
- mysql =》 mysql 命令恢复数据库
- 高精度数字
- UVALive 6902 Three Squares(二分 + 搜索)
- runtime——函数替换
- [蓝牙] 5、Battery Service module
- UVALive 6901 String Transformation(贪心)
- 例题5-1 UVA 10474 Where is the Marble?大理石在哪?
- mysql => mysql数据库备份 命令
- 【Beta阶段】第三次Scrum Meeting!
- 基本类型
- Java 对象在内存中的存储
- NestedScrollingParent, NestedScrollingChild  详解
- Python抓取天猫商品详细信息及交易记录
- 算法-排序算法