POJ 2182 Lost Cows

题意: 有n个数,从1到n,打乱顺序,现输入n-1个数,第i个数表示序列中第1到i-1的数比第i个数小的个数.

要求输出该序列。从后往前每次求“第k小”,如样例,第五个数前面有0个比它小的,它一定是1,将1在

线段树中删除,再看第四个数,前面有1个比它小的,它就是2、3、4、5中第2小的,以此类推。线段树求

第k小一般思路:数组中存放区间元素个数,自顶向下,左边个数小于k就走右边,并用k去掉左边个数,

否则走向左边,直到叶子结点就是第k小。 

/*Accepted    264K    47MS    C++    1061B    2012-07-24 12:19:42*/

#include<cstdio>

#include<cstring>



const int MAXN = 10005;

int T[MAXN << 2], cow[MAXN];

int M;



void build( int n)

{

    int i;

    for( M = 1; M < n + 2; M <<= 1)

    memset( T, 0, sizeof(int) * (M << 2));

    for( i = 1; i <= n; i ++)

        T[i + M] = 1; //存的是值为i的个数

    for( i = M - 1; i > 0 ; i --)

        T[i] = T[i << 1] + T[i << 1 | 1];

}



void update( int i)

{

    for( ; i ^= 1; i >>= 1)

        T[i >> 1] = T[i] + T[i ^ 1];

}



int query( int k)

{

    int i, j;

    for( i = 1; i < M;)

    {

        if( T[i << 1] < k)

            k -= T[i << 1], i = i << 1 | 1;

        else

            i <<= 1;

    }

    -- T[i]; //删除值为i-M的点

    update(i);

    return i - M;

}



int main()

{

    int n, i;

    while( scanf( "%d", &n) == 1)

    {

        build(n);

        cow[0] = 0;

        for( i = 1; i < n; i ++)

            scanf( "%d", &cow[i]);

        for( i = n - 1; i >= 0; i --)

            cow[i] = query( cow[i] + 1);

        for( i = 0; i < n; i ++)

            printf( "%d\n", cow[i]);

    }

}

 

 

你可能感兴趣的:(poj)