您的位置:首页 > 其它

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。

【参考代码】

#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;
}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: