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 }

 

你可能感兴趣的:(number)