pku K-th Number 划分树

pku K-th Number 划分树

题意为求一个给定区间[s,e]内的第k小元素。
这里用到一种新的数据结构,叫做划分树。网上介绍很多了,我就不多说了。
不过我对这种结构有点小体会:
可以当作线段树来理解,但是查询操作是基于有多少元素被划分到左区间来定位的。而在查询操作中给出的[s,e]并不是区间[s,e],而是该区间内第s到第e个元素
代码写的有点搓。。有时间重写下。。
 1  import  java.io. * ;
 2  import  java.util.Arrays;
 3  class  node
 4  {
 5      int  s,e;
 6      int  num[],count[];
 7  }
 8  public   class  Main {
 9 
10       /**
11       *  @param  args
12        */
13       static  StreamTokenizer in = new  StreamTokenizer( new  BufferedReader( new  InputStreamReader(System.in)));
14       static   int  readInt()  throws  IOException
15      {
16          in.nextToken();
17           return  ( int )in.nval;
18      }
19       static  node st[];
20       static   int  data[];
21       static   void  make( int  pos)
22      {
23          int  s = st[pos].s,e = st[pos].e;
24          if (s != e)
25         {
26              int  mid = (s + e) / 2 ;
27             st[pos << 1 ].s = s;
28             st[pos << 1 ].e = mid;
29             st[pos << 1 ].num = new   int [mid - s + 1 ];
30             st[pos << 1 ].count = new   int [mid - s + 1 ];
31             st[(pos << 1 ) + 1 ].s = mid + 1 ;
32             st[(pos << 1 ) + 1 ].e = e;
33             st[(pos << 1 ) + 1 ].num = new   int [e - mid];
34             st[(pos << 1 ) + 1 ].count = new   int [e - mid];
35              int  c1 = 0 ,c2 = 0 ;
36              for ( int  i = s;i <= e;i ++ )
37             {
38                  if (st[pos].num[i - s] <= data[mid])
39                 {
40                     st[pos << 1 ].num[c1 ++ ] = st[pos].num[i - s];
41                     st[pos].count[i - s] = (i == s ? 0 :st[pos].count[i - s - 1 ]) + 1 ;
42                 }
43                  else
44                 {
45                     st[(pos << 1 ) + 1 ].num[c2 ++ ] = st[pos].num[i - s];
46                     st[pos].count[i - s] = (i == s ? 0 :st[pos].count[i - s - 1 ]);
47                 }
48             }
49             make(pos << 1 );
50             make((pos << 1 ) + 1 );
51         }
52      }
53       static   int  find( int  s, int  e, int  k, int  pos)
54      {
55               if (st[pos].s == st[pos].e)  return  st[pos].num[s];
56               int  left = st[pos].count[e] - (s == 0 ? 0 :st[pos].count[s - 1 ]);
57               if (k <= left)
58                 return  find(s == 0 ? 0 :st[pos].count[s - 1 ],st[pos].count[e] - 1 ,k,pos << 1 );
59               else
60                 return  find(s == 0 ? 0 :s - st[pos].count[s - 1 ],e + 1 - st[pos].count[e] - 1 ,k - left,(pos << 1 ) + 1 );
61                
62      }
63       public   static   void  main(String[] args)  throws  IOException{
64           int  n = readInt(),q = readInt();
65          st = new  node[ 4 * n];
66           for ( int  i = 0 ;i < st.length;i ++ )
67              st[i] = new  node();
68          st[ 1 ].num = new   int [n];
69          st[ 1 ].count = new   int [n];
70           for ( int  i = 0 ;i < n;i ++ )
71              st[ 1 ].num[i] = readInt();
72          data = st[ 1 ].num.clone();
73          Arrays.sort(data);
74          st[ 1 ].s = 0 ;
75          st[ 1 ].e = n - 1 ;
76          make( 1 );
77           while ((q -- ) != 0 )
78            System.out.println(find(readInt() - 1 ,readInt() - 1 ,readInt(), 1 ));
79 
80      }
81 
82  }
83 

你可能感兴趣的:(pku K-th Number 划分树)