首页 > 代码库 > POJ2104 区间第k小

POJ2104 区间第k小

题意就是区间第k大……

题解:

前段时间用主席树搞掉了……

如今看到划分树,是在想来写一遍,结果18号对着学长的代码调了一上午连样例都没过,好桑心……

今天在做NOI2010超级钢琴,忽然发现用划分树很直观,果断决定再战划分树

对着网上的c++代码抄了一遍,A了,可是这编程复杂度有点高,忽然又看见盾哥的代码

很简短,和我原先的代码差不多,他怎么能A了呢……(后来发现区间第k小,我却写的第k大……sb啊)

考虑到盾哥的程序用到了离散化,因此没有考虑存在两个数相等的情况,这样就使代码减少很多

我报着试一试的心态把我认为肯定对的代码随机生成了几组大数据和盾哥的程序对拍,然后就对上了

好的,以后就用盾哥的程序

代码:

c++翻译来的:

 1 var  s,t:array[0..20,0..200000] of longint; 2      a,rk:array[0..200000] of longint; 3      i,n,m,x,y,k,j:longint; 4  procedure sort(l,r:longint); 5  var i,j,m,temp:longint; 6  begin 7  i:=l;j:=r;m:=a[(i+j)>>1]; 8  repeat 9   while a[i]<m do inc(i);10   while a[j]>m do dec(j);11   if i<=j then12    begin13    temp:=a[i];a[i]:=a[j];a[j]:=temp;14    inc(i);dec(j);15    end;16  until i>j;17  if i<r then sort(i,r);18  if j>l then sort(l,j);19  end;20   procedure init;21    begin22      readln(n,m);23      for i:=1 to n do read(a[i]);t[0]:=a;24      sort(1,n);25    end;26  procedure build(h,l,r:longint);27   var  mid,i,lp,rp,lm:longint;28   begin29   mid:=(l+r)>>1;lm:=mid-l+1;lp:=l;rp:=mid+1;30   for i:=l to mid do31    if a[i]<a[mid] then dec(lm);32   for i:=l to r do33    begin34    if i=l then s[h,i]:=0 else s[h,i]:=s[h,i-1];35    if t[h,i]=a[mid] then36     begin37     if lm<>0 then38      begin39      dec(lm);inc(s[h,i]);t[h+1,lp]:=t[h,i];inc(lp);40      end41     else begin t[h+1,rp]:=t[h,i];inc(rp);end;42     end43    else44     if t[h,i]<a[mid] then begin inc(s[h,i]);t[h+1,lp]:=t[h,i];inc(lp);end45    else begin t[h+1,rp]:=t[h,i];inc(rp);end;46    end;47   if l=r then exit;48   build(h+1,l,mid);49   build(h+1,mid+1,r);50   end;51  function find(h,l,r,x,y,k:longint):longint;52   var mid,ll,rr:longint;53   begin54   if l=r then exit(t[h,l]);55   mid:=(l+r)>>1;56   if l=x then ll:=0 else ll:=s[h,x-1];rr:=s[h,y]-ll;57   if rr>=k then exit(find(h+1,l,mid,l+ll,l+ll+rr-1,k))58   else exit(find(h+1,mid+1,r,mid+1+x-l-ll,mid+1+y-l-ll-rr,k-rr));59   end;60  procedure main;61   begin62    build(0,1,n);63    for i:=1 to m do64     begin65      readln(x,y,k);66      writeln(find(0,1,n,x,y,k));67     end;68   end;69 begin70   init;71   main;72 end.       
View Code

盾哥的:

 1 program poj2104; const maxn=200000; 2 var 3   a,b:array[0..maxn] of longint; 4   s,d:array[1..20,0..maxn] of longint; 5   n,m,i,j,x,y,z,ls,rs,mid,p:longint; 6  7 procedure sort(l,r:longint); var i,j,x,y:longint; 8 begin 9   i:=l;j:=r;x:=a[(i+j)>> 1];10   repeat11     while b[a[i]]<b[x] do inc(i);12     while b[a[j]]>b[x] do dec(j);13     if i<=j then begin14       y:=a[i];a[i]:=a[j];a[j]:=y;15       inc(i);dec(j);16     end;17   until i>j;18   if l<j then sort(l,j);19   if i<r then sort(i,r);20 end;21 22 procedure buildtree(h,l,r:longint);var mid:longint;23 begin24   if l=r then exit;25   mid:=(l+r+1)>> 1;p:=0;26   for i:=l to r do27     if d[h,i]<mid then begin28       d[h+1,l+p]:=d[h,i];29       inc(p);s[h,i]:=p;30     end else begin31       d[h+1,mid+i-l-p]:=d[h,i];32       s[h,i]:=p;33     end;34   buildtree(h+1,l,mid-1);35   buildtree(h+1,mid,r);36 end;37 38 function find(h,ll,rr,l,r,k:longint):longint;39 begin40   if l=r then exit(d[h,r]);41   if l=ll then ls:=0 else ls:=s[h,l-1];42   rs:=s[h,r];mid:=(ll+rr+1)>> 1;43   if rs-ls<k44     then find:=find(h+1,mid,rr,l-ll-ls+mid,r-ll-rs+mid,k-rs+ls)45     else find:=find(h+1,ll,mid-1,ls+ll,rs+ll-1,k);46 end;47 48 begin49   readln(n,m);50   for i:=1 to n do begin read(b[i]);a[i]:=i; end;51   sort(1,n);52   for i:=1 to n do d[1,a[i]]:=i;53   buildtree(1,1,n);54   for i:=1 to m do begin55     readln(x,y,z);56     writeln(b[a[find(1,1,n,x,y,z)]]);57   end;58 end.   
View Code

我最先抄的:

 1 const maxn=100000+10; 2 type arrtype=array[0..maxn] of longint; 3 var s,z:array[0..20,0..maxn] of longint; 4     a,b,rk:arrtype; 5     i,j,n,m,x,y,k:longint; 6 procedure sort(var a:arrtype;l,r:longint); 7  var i,j,m,temp:longint; 8  begin 9  i:=l;j:=r;m:=a[(i+j)>>1];10  repeat11   while a[i]<m do inc(i);12   while a[j]>m do dec(j);13   if i<=j then14    begin15    temp:=a[i];a[i]:=a[j];a[j]:=temp;16    temp:=rk[i];rk[i]:=rk[j];rk[j]:=temp;17    inc(i);dec(j);18    end;19  until i>j;20  if i<r then sort(a,i,r);21  if j>l then sort(a,l,j);22  end;23 procedure init;24  begin25  readln(n,m);26  for i:=1 to n do read(a[i]);readln;b:=a;27  for i:=1 to n do rk[i]:=i;28  sort(a,1,n);29  end;30 procedure build(h,l,r:longint);31  var i,p,mid:longint;32  begin33  mid:=(l+r)>>1;p:=0;34  for i:=l to r do35   if z[h,i]<=mid then36    begin37     z[h+1,l+p]:=z[h,i];38     inc(p);39     s[h,i]:=p;40    end41   else42    begin43     z[h+1,mid+1+i-p-l]:=z[h,i];44     s[h,i]:=p;45    end;46  if l=r then exit;47  build(h+1,l,mid);48  build(h+1,mid+1,r);49  end;50 function find(h,l,r,x,y,k:longint):longint;51  var ll,rr,mid:longint;52  begin53  if l=r then exit(z[h,l]);54  mid:=(l+r)>>1;55  if l=x then ll:=0 else ll:=s[h,x-1];rr:=s[h,y];56  if rr-ll>=k then exit(find(h+1,l,mid,l+ll,l+rr-1,k))57  else exit(find(h+1,mid+1,r,mid+1+x-l-ll,mid+1+y-l-rr,k-(rr-ll)));58  end;59 procedure main;60  begin61  for i:=1 to n do z[1,rk[i]]:=i;62  build(1,1,n);63  for i:=1 to m do64   begin65   readln(x,y,k);66   writeln(b[rk[find(1,1,n,x,y,k)]]);67   end;68  end;69 begin70  init;71  main;72 end.        
View Code

盾哥的代码风格确实比我好很多,值得学习