POJ 2352 Stars 线段树 pascal

来源:互联网 发布:linux语句解释说明 编辑:程序博客网 时间:2024/06/08 18:04

题目大意:给定一个二维网图,里面有很多颗星星,每一颗星星都有他自己的level,对于每一颗,他的level是在他左下方的星星个数(允许是边界。其实换句话来说就是在原点到这个点的坐标内的除他本身所有点的个数),最后求出每个level(0~n-1)的个数各有多少个

题目分析:由题可得,level[x]的个数其实就是他左下方星星的个数,那么由于y值是递增的,所以出现一种很微妙的关系:我们在建好树之后去计算星星的数量时等于从低到高开始找,那么也就意味着说即使x值在存储中多次出现,但他的所包含的星星的数量由于前面的更新而发生了改变,所包含的数量会增加。所以我们只需要存储其很坐标的值就可以了,然后对于x建树,每计算完一个星星之后把这个星星所被被包含树的节点的w增加。如果说读入时y的大小不是递增的话还要加一个排序,以y的大小为核心去改变每个x的位置。

代码:

type  rec=record        l,r,w:longint;      end;var  tree:array[0..32000*4] of rec;    //树  ans:array[0..32000] of longint;   //计算     a:array[1..15000] of longint;     //存储x  b,i,max,n:longint;  procedure build(l,r,i:longint);  var    mid:longint;  begin    tree[i].l:=l;    tree[i].r:=r;    tree[i].w:=0;    if l=r then exit;    mid:=(tree[i].l+tree[i].r) div 2;    build(l,mid,i*2);    build(mid+1,r,i*2+1);  end;  function find(l,r,i:longint):longint;  var    mid,sum:longint;  begin    if (tree[i].l=l) and (tree[i].r=r) then exit(tree[i].w)    else      begin        mid:=(tree[i].l+tree[i].r) div 2; sum:=0;        if l>mid then sum:=sum+find(l,r,i*2+1)        else          if r<=mid then sum:=sum+find(l,r,i*2)          else            sum:=sum+find(l,mid,i*2)+find(mid+1,r,i*2+1);        exit(sum);      end;  end;  procedure insert(x,i:longint);  var    mid:longint;  begin    inc(tree[i].w);    if (tree[i].l=tree[i].r) and (tree[i].r=x) then exit;    mid:=(tree[i].l+tree[i].r) div 2;    if x<=mid then insert(x,i*2)    else      insert(x,i*2+1);  end;begin  readln(n); max:=0;  fillchar(ans,sizeof(ans),0);  for i:=1 to n do  begin    readln(a[i],b);    if a[i]>max then max:=a[i];        //求出x的最大值  end;  build(0,max,1);       //建树  for i:=1 to n do  begin    inc(ans[find(0,a[i],1)]);       //计算个数(会重复做一个点,原因看分析)    insert(a[i],1);                 //更新  end;  for i:=0 to n-1 do writeln(ans[i]);end.



0 1
原创粉丝点击