您的位置:首页 > 其它

Hdu2795-Billboard-【线段树】-【有】

2017-08-17 22:46 357 查看
传送门:http://acm.hdu.edu.cn/showproblem.php?pid=2795

不贴英文题了,,贴了也没用( ╯□╰ )  翻译之后看了好久才理解题意

中文题意:

在学校的入口处有一个巨大的矩形广告牌,高为h,宽为w。所有种类的广告都可以贴,比如ACM的广告啊,还有餐厅新出了哪些好吃的,等等。。

在9月1号这天,广告牌是空的,之后广告会被一条一条的依次贴上去。

每张广告都是高度为1宽度为wi的细长的矩形纸条。

贴广告的人总是会优先选择最上面的位置来帖,而且在所有最上面的可能位置中,他会选择最左面的位置,而且不能把已经贴好的广告盖住。

如果没有合适的位置了,那么这张广告就不会被贴了。

现在已知广告牌的尺寸和每张广告的尺寸,求每张广告被贴在的行编号。

Input

多组样例,不超过40个。

对每组样例,第一行包含3个整数h,w,n(1 <= h,w <= 10^9; 1 <= n <= 200,000) -广告牌的尺寸和广告的个数。

下面n行每行一个整数 wi (1 <= wi <= 10^9) - 第i张广告的宽度.

Output

对每张广告,输出它被贴在的行编号(是1到h之间的数),顶部是第一行。如果某广告不能被贴上,则输出-1。

在学校的入口处有一个巨大的矩形广告牌,高为h,宽为w。所有种类的广告都可以贴,比如ACM的广告啊,还有餐厅新出了哪些好吃的,等等。。
Sample Input
3 5 5
2
4
3
3
3

Sample Output
1
2
1
3
-1


 
在9月1号这天,广告牌是空的,之后广告会被一条一条的依次贴上去。
 
每张广告都是高度为1宽度为wi的细长的矩形纸条。
 
贴广告的人总是会优先选择最上面的位置来帖,而且在所有最上面的可能位置中,他会选择最左面的位置,而且不能把已经贴好的广告盖住。

如果没有合适的位置了,那么这张广告就不会被贴了。
 
现在已知广告牌的尺寸和每张广告的尺寸,求每张广告被贴在的行编号。

解题:感觉今天学的树状结构根本没用到2333     首先每个广告的高度都是1  可以将整个广告旋转90°,这时可以将高作为端点,宽w作为端点值,,这样一个线段树就出来了  很神奇

利用线段树的思想,先以每一行的长度即矩形的宽度为叶子节点建立一个树,每一个非叶子节点表示该节点所在区间的剩余的最大长度,建好树之后我们得到的树的根节点表示的是整个矩形的剩余的最大长度(可能是广告牌的宽,也可能是最大的剩余宽),根据这个条件就可以直接得到该条广告是否能够写上去,能写上去的话我们可以直接更新和这个叶子节点有关的所有节点。

当某个广告的宽度wi不大于整段的最大值时(更新之后),一定能放进去,因为h大于n时一定有空余的行数  小于时如果不大于最大的空闲空间,就能放进去。

贴一个感觉很有心的博主关于线段树http://blog.csdn.net/metalseed/article/details/8039326

#include<cstdio>
#include<algorithm>
using namespace std;
struct Node
{
int l,r,maxw;//表示剩余空间的最大值
}Tree[200005<<2];
int h,w,n,ans;
void PushUp(int o)
{
Tree[o].maxw =max(Tree[o*2].maxw ,Tree[o*2+1].maxw );
}
void Build(int o,int l,int r)
{
Tree[o].l =l;
Tree[o].r =r;
Tree[o].maxw =w;//每一个叶子节点在开始的时候的长度就是他的最大长度,即矩形的宽度
if(l==r)
return ;
int mid=(l+r)>>1;
Build(o*2,l,mid);
Build(o*2+1,mid+1,r);
// PushUp(o);
}
void Query(int o,int l,int r,int x)
{
if(Tree[o].l ==Tree[o].r)
{
Tree[o].maxw -=x; //查询到叶子结点时更新节点,
// return Tree[o].l; 即每次查找到这个点,就将这个长度减去,表示只剩下这些空间
ans=Tree[o].l ; // 返回所在的叶子的位置,即矩形的行位置
return ;
}
int mid=(l+r)>>1;
if(x<=Tree[o*2].maxw ) //如果宽度小于左节点,,就去左找,总之优先左节点
Query(o*2,l,mid,x);
else
Query(o*2+1,mid+1,r,x);
PushUp(o);

}
int main()
{
while(scanf("%d%d%d",&h,&w,&n)!=EOF)
{
h=min(h,n);//节省空间 因为如果 h 比 n 大 只取小的就行 多了也用不完
Build(1,1,h);
for(int i=1; i<=n; i++)
{
int t;
scanf("%d",&t);
if(Tree[1].maxw <t) //Tree[1].maxw 是跟结点一定是最大值
{
printf("-1\n");
continue;
}
else
{
Query(1,1,h,t);// h 就是模板里的 n
printf("%d\n",ans);
}
}
}
return 0;
}
/*
Sample Input

3 5 5 2 4 3 3 3

Sample Output

1 2 1 3 -1
*/

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