POJ 2104 K-th Number(划分树)

题目链接

参考HH大神的模版。对其中一些转移,还没想清楚,大体明白上是怎么回事了,划分树就是类似快排,但有点点区别的。多做几个题,慢慢理解。

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <algorithm>
  4 using namespace std;
  5 #define lson l,m,rt<<1
  6 #define rson m+1,r,rt<<1|1
  7 #define N 100100
  8 struct node
  9 {
 10     int l,r;
 11 }tree[4*N];
 12 int sorted[N];
 13 int lnum[20][N];
 14 int val[20][N];
 15 
 16 void build(int d,int l,int r,int rt)
 17 {
 18     int m,lsame,i,lpos,rpos,same;
 19     tree[rt].l = l;
 20     tree[rt].r = r;
 21     if(l == r) return ;
 22     m = (l+r)>>1;
 23     lsame = (m - l + 1);
 24     for(i = l;i <= r;i ++)
 25     {
 26         if(val[d][i] < sorted[m])
 27         lsame --;
 28     }
 29     lpos = l;
 30     rpos = m+1;
 31     same = 0;
 32     for(i = l;i <= r;i ++)
 33     {
 34         if(i == l)//lnum[d][i]表示[tree[rt].l, i ]区域里有多少个数分到左边
 35         lnum[d][i] = 0;
 36         else
 37         lnum[d][i] = lnum[d][i-1];
 38         if(val[d][i] < sorted[m])
 39         {
 40             lnum[d][i] ++;
 41             val[d+1][lpos++] = val[d][i];
 42         }
 43         else if(val[d][i] > sorted[m])
 44         {
 45             val[d+1][rpos++] = val[d][i];
 46         }
 47         else
 48         {
 49             if(same < lsame)
 50             {
 51                 same ++;
 52                 lnum[d][i] ++;
 53                 val[d+1][lpos++] = val[d][i];
 54             }
 55             else
 56             {
 57                 val[d+1][rpos++] = val[d][i];
 58             }
 59         }
 60     }
 61     build(d+1,lson);
 62     build(d+1,rson);
 63 }
 64 int query(int d,int k,int l,int r,int rt)
 65 {
 66     int s,ss,nl,nr,m,rs,rss;//s表示[ l , r ]有多少个分到左边
 67     if(l == r)//ss表示 [tree[idx].left , l-1 ]有多少个分到左边
 68     {
 69         return val[d][l];
 70     }
 71     if(l == tree[rt].l)
 72     {
 73         s = lnum[d][r];
 74         ss = 0;
 75     }
 76     else
 77     {
 78         s = lnum[d][r] - lnum[d][l-1];
 79         ss = lnum[d][l-1];
 80     }
 81     if(s >= k)
 82     {
 83         nl = ss + tree[rt].l;
 84         nr = ss + tree[rt].l + s - 1;
 85         return query(d+1,k,nl,nr,rt<<1);
 86     }
 87     else
 88     {
 89         m = (tree[rt].l + tree[rt].r)>>1;
 90         rss = l - tree[rt].l - ss;
 91         rs = r - l + 1 - s;
 92         nl = m + rss + 1;
 93         nr = m + rs + rss;
 94         return query(d+1,k-s,nl,nr,rt<<1|1);
 95     }
 96 }
 97 int main()
 98 {
 99     int i,n,m,x,y,k;
100     while(scanf("%d%d",&n,&m)!=EOF)
101     {
102         for(i = 1;i <= n;i ++)
103         {
104             scanf("%d",&val[0][i]);
105             sorted[i] = val[0][i];
106         }
107         sort(sorted+1,sorted+n+1);
108         build(0,1,n,1);
109         for(i = 0;i < m;i ++)
110         {
111             scanf("%d%d%d",&x,&y,&k);
112             printf("%d\n",query(0,k,x,y,1));
113         }
114     }
115     return 0;
116 }

 

posted @ 2013-08-02 17:40  Naix_x  阅读(217)  评论(0编辑  收藏  举报