hdu 2795 Billboard 线段树

来源:互联网 发布:51单片机at指令 编辑:程序博客网 时间:2024/06/06 00:53

题目大意:给一个h*w的公告牌,h是高度,w是宽度,一个单位高度为一行,然后会有一些公告贴上去,公告是1*wi大小的长纸条,优先贴在最上面并且最左边的位置,如果没有空间贴的下,就输出-1,如果可以,就输出所贴的位置(第几行)。

分析:给我感觉这题是比较高层次的线段树的应用,因为我是看了题解才想到的(也可能是我比较水)。要想知道公告贴哪里,首先得知道有没有位置贴公告吧,所以就用线段树节点区间【a,b】表示第a行到第b行中最大的空位,叶节点区间【x,x】表示该行剩下多少个位置。若放不下则返回-1,否则的话就继续往下找(优先找左节点),一直找到叶节点并更新叶节点以及它父节点的权值就好了。

下面附程序:

var  h,w,n,i,x:longint;  t:array[1..600000,1..3] of longint;function max(x,y:longint):longint;begin  if x>y then exit(x)         else exit(y);end;procedure hehe(d,l,r:longint);var  m:longint;begin  t[d,1]:=l;  t[d,2]:=r;  t[d,3]:=w;  if l=r then exit;  m:=(l+r) div 2;  hehe(d*2,l,m);  hehe(d*2+1,m+1,r);end;function work(d,x:longint):longint;begin  if t[d,3]<x then exit(-1);  if t[d,1]=t[d,2] then  begin    t[d,3]:=t[d,3]-x;    exit(t[d,1]);  end;  if t[d*2,3]>=x    then work:=work(d*2,x)    else work:=work(d*2+1,x);  t[d,3]:=max(t[d*2,3],t[d*2+1,3]);end;function min(x,y:longint):longint;begin  if x<y then exit(x)         else exit(y); end;begin  while not eof do  begin    readln(h,w,n);    hehe(1,1,min(n,h));    for i:=1 to n do    begin      readln(x);      writeln(work(1,x));    end;  end;end.


0 0