HDU 3016 Man Down

该题是一道,成段更新,单点查询(简单线段树+简单DP),这个题与http://poj.org/problem?id=1436思想差不多,这里我就不重复了,这里就是要处理最大值的问题也就是DP;

我有的方法就是以该条边的两个端点往下搜索,如果下面有可见的边,选择值的那条边,然后再进行更新;

 

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
class Node
{
public:
int l ,r , sum,cover;
};
Node tree[2000024];
class segment
{
public:
int x1,x2,y,value;
};
segment seg[150024];
bool cmp( segment a, segment b )
{
return a.y < b.y;
}
class Tree
{
public:
void Maketree( int l , int r, int cnt );
void Update( int l , int r ,int cnt, int id, int sum );
int Max( int a, int b )
{ return a>b?a:b; }
int Query( int cnt,int num );
};

void Tree::Maketree( int l , int r , int cnt )
{
tree[cnt].l = l ;
tree[cnt].r = r;
tree[cnt].cover = -1;
tree[cnt].sum = 0;
if( l == r )
return ;
int mid = ( l + r )>>1;
Maketree( l , mid , cnt*2 );
Maketree( mid + 1 , r , cnt*2+1 );
}
void Tree::Update( int l , int r , int cnt , int id ,int sum)
{
if( l<=tree[cnt].l&&r>=tree[cnt].r )
{
tree[cnt].sum=sum+seg[id].value;
tree[cnt].cover = id;
// printf( "l==%d r==%d sum==%d\n",tree[cnt].l ,tree[cnt].r,tree[cnt].sum);
return ;
}
else
{
if( tree[cnt].cover !=-1 )//向下进行更新
{
tree[cnt*2].cover = tree[cnt*2+1].cover = tree[cnt].cover;
tree[cnt].cover = -1;
tree[cnt*2].sum = tree[cnt*2+1].sum = tree[cnt].sum;
}
int mid = ( tree[cnt].r + tree[cnt].l )>>1;
if( l > mid ) Update( l ,r ,cnt*2+1, id ,sum );
else
{
if( r <= mid ) Update( l ,r ,cnt * 2 , id ,sum );
else
{
Update( l ,mid , cnt*2 , id ,sum );
Update( mid + 1 , r , cnt*2+1 , id ,sum );
}
}
}
}
int Tree::Query( int cnt , int num )
{
if( tree[cnt].cover!=-1 )
{
// printf( "%d %d\n",tree[cnt].sum,num );
return tree[cnt].sum;
}
int mid = ( tree[cnt].l + tree[cnt].r )>>1;
if( num>mid ) return Query( cnt*2+1 , num );
else return Query( cnt*2 , num );
return 0;
}
int main( )
{
int n;
while( scanf( "%d",&n )==1 )
{
Tree e;
e.Maketree( 0,200000 , 1 );
for( int i = 0; i < n ; i++ )
{

scanf( "%d%d%d%d",&seg[i].y,&seg[i].x1,&seg[i].x2,&seg[i].value );
seg[i].x1 *= 2;
seg[i].x2 *= 2;
}
sort( seg , seg+n , cmp ); //对Y进行排序
for( int i = 0 ; i < n-1 ; i++ )
{
int sum = e.Max( e.Query( 1 , seg[i].x1 ),e.Query( 1 , seg[i].x2 ) );//对两个端点进行选择最大值
e.Update( seg[i].x1 , seg[i].x2, 1 , i , sum );//进行更新

}
int sum = 100 + e.Max( e.Query( 1 , seg[n-1].x1 ),e.Query( 1 , seg[n-1].x2 ) ) +seg[n-1].value;//最后一个段进行处理
printf( sum>0?"%d\n":"-1\n",sum);
}
return 0;
}


posted @ 2012-02-28 15:22  wutaoKeen  阅读(218)  评论(0编辑  收藏  举报