hdu 2852 KiKi's K-Number 线段树求第k大数

题意:给定一个容器,里面存放各种数值,规定三个操作,一个是在容器中增加一个数值,一个是在容器中删掉一个数值,一个是询问容器中比a大的数中第k大的数,将其输出。如果在删除过程中没有这个数,则输出"No Elment!",如果容器中没有比a大的第k个数,则输出"Not Find!".

这题因为是在线插入、删除和查找,所以就想到用线段树(树状数组也可以)。因为读入的数的范围是1到100000,所以就种一棵100000的线段树,每一个区间记录该区间有多少个数。然后插入和删除就是基本的操作啦。至于第三个操作,就先求出不大于a的数有多少个(设为x个),然后求第x+k大的数就是好啦。

代码:

var
  n,x,y,u,ans,i:longint;
  t:array[1..300000,1..3] of longint;

procedure hehe(d,l,r:longint);
var
  m:longint;
begin
  t[d,1]:=l;
  t[d,2]:=r;
  t[d,3]:=0;
  if l=r then exit;
  m:=(l+r) div 2;
  hehe(d*2,l,m);
  hehe(d*2+1,m+1,r);
end;

procedure insert(d,x:longint);
var
  m:longint;
begin
  inc(t[d,3]);
  if (t[d,1]=x)and(t[d,2]=x) then exit;
  m:=(t[d,1]+t[d,2]) div 2;
  if x<=m
    then insert(d*2,x)
    else insert(d*2+1,x);
end;

function delete(d,x:longint):boolean;
var
  m:longint;
begin
  if (t[d,1]=t[d,2])and(t[d,1]=x) then
  begin
    if t[d,3]>0 then
    begin
      dec(t[d,3]);
      exit(true);
    end;
    exit(false);
  end;
  m:=(t[d,1]+t[d,2]) div 2;
  if x<=m
    then delete:=delete(d*2,x)
    else delete:=delete(d*2+1,x);
  if delete then dec(t[d,3]);
end;

function count(d,x:longint):longint;
var
  m:longint;
begin
  if t[d,1]=t[d,2] then exit(t[d,3]);
  m:=(t[d,1]+t[d,2]) div 2;
  if x<=m
    then count:=count(d*2,x)
    else count:=count(d*2+1,x)+t[d*2,3];
end;

function find(d,x:longint):longint;
var
  m:longint;
begin
  if (t[d,3]=0)or(t[d,3]<x) then exit(0);
  if t[d,1]=t[d,2] then exit(t[d,1]);
  if x<=t[d*2,3]
    then find:=find(d*2,x)
    else find:=find(d*2+1,x-t[d*2,3]);
end;

begin
  while not eof do
  begin
    readln(n);
    hehe(1,0,100000);
    for i:=1 to n do
    begin
      read(x);
      if x=0
        then begin
               readln(y);
               insert(1,y);
             end
        else if x=1
               then begin
                      readln(y);
                      if delete(1,y)=false then writeln('No Elment!');
                    end
               else begin
                      readln(x,y);
                      u:=count(1,x);
                      ans:=find(1,u+y);
                      if ans=0
                        then writeln('Not Find!')
                        else writeln(ans);
                    end;
    end;
  end;
end.


你可能感兴趣的:(hdu 2852 KiKi's K-Number 线段树求第k大数)