HDU 2795 Billboard

题意:有一块长方形的广告板,往上面贴广告,然后给n个1*wi的广告,要求把广告贴上去,如果前面的行可以贴,就要贴前面的并且要靠左贴,前面的贴不下就贴在下面,

广告的高度是wi,如果能贴在上面输出最小的高度,如果不能就输出-1。

解题思路:如果以行数为区间,建立线段树,他给的h有10^9次,是创不了10^9这么大的数组的。然而我们知道给定N个广告,应为宽度一定,那么最高也不会超过N;只是我们可以开4×N为数组来建树;我把最后树的叶子节点表示广告牌的高度,并且左边的高度小于右边的;而父节点存储子节点的最大剩余值,如果最大值都比wi都小,则表示该节点不可能贴上广告,那么我们就要回朔到上一个节点,也就是下层;这就是该题的思路;

注意:当我们找到指定的层数是我们就要直接终止继续回朔,我们可以用个全局变量标记。

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
class Node
{
public:
int max,l,r,mid,floor;
};
Node tree[800024];
int flag,floor1;
class Tree
{
public:
void Maketree( int l,int r,int cnt ,int& floor,int length);
void research( int cnt,int width );
int Max( int a,int b )
{ return a>b?a:b; }
};
void Tree::Maketree( int l, int r ,int cnt , int& floor ,int length)
{
if( l==r )
{
tree[cnt].l = tree[cnt].r =tree[cnt].mid=l;
tree[cnt].max = length;
tree[cnt].floor = floor;
floor++;
return;
}
else
{
tree[cnt].l = l;
tree[cnt].r = r;
tree[cnt].mid = ( l+r )>>1;
tree[cnt].floor = 0;
Maketree( l , tree[cnt].mid , cnt*2 , floor , length );
Maketree( tree[cnt].mid + 1 , r ,cnt*2+1, floor , length );
tree[cnt].max = Max( tree[cnt*2].max ,tree[cnt*2+1].max );
}
}
void Tree::research( int cnt ,int width)
{
if( flag==1 )
{
tree[cnt].max = Max( tree[cnt*2].max,tree[cnt*2+1].max );
return ;
}
if( tree[cnt].max>=width)
{
if( tree[cnt].floor>0 )
{
flag=1;
tree[cnt].max -= width;
floor1=tree[cnt].floor;
return ;
}
else
{
research( cnt*2,width );
if( flag==1 )
{
tree[cnt].max = Max( tree[cnt*2].max,tree[cnt*2+1].max );
return ;
}
research( cnt*2+1,width );
if( flag==1 )
{
tree[cnt].max = Max( tree[cnt*2].max,tree[cnt*2+1].max );
return ;
}
}
}
}

int main( )
{
int h,w,n;
while( scanf( "%d%d%d",&h,&w,&n )==3 )
{
Tree e;
int floor = 1;
if( n<=h )
e.Maketree( 1,n,1,floor,w );
else e.Maketree( 1,h,1,floor,w );
while( n-- )
{
floor1=-1;
flag=0;
scanf( "%d",&w );
e.research( 1,w );
printf( "%d\n",floor1 );
}
}
return 0;
}


你可能感兴趣的:(HDU)