poj 2182

来源:互联网 发布:阿里云代理 几折 编辑:程序博客网 时间:2024/05/03 23:48

Description

N (2 <=N <= 8,000) cows have unique brands in the range 1..N. In a spectaculardisplay of poor judgment, they visited the neighborhood 'watering hole' anddrank a few too many beers before dinner. When it was time to line up for theirevening meal, they did not line up in the required ascending numerical order oftheir brands. 
Regrettably, FJ does not have a way to sort them. Furthermore, he's not verygood at observing problems. Instead of writing down each cow's brand, hedetermined a rather silly statistic: For each cow in line, he knows the numberof cows that precede that cow in line that do, in fact, have smaller brandsthan that cow. 
Given this data, tell FJ the exact ordering of the cows. 

Input

* Line 1:A single integer, N 
* Lines 2..N: These N-1 lines describe the number of cows that precede a givencow in line and have brands smaller than that cow. Of course, no cows precedethe first cow in line, so she is not listed. Line 2 of the input describes thenumber of preceding cows whose brands are smaller than the cow in slot #2; line3 describes the number of preceding cows whose brands are smaller than the cowin slot #3; and so on. 

Output

* Lines1..N: Each of the N lines of output tells the brand of a cow in line. Line #1of the output tells the brand of the first cow in line; line 2 tells the brandof the second cow; and so on.

题目大意:

N个牛排队吃饭,这N个牛都有编号(1、2、3、4、5、……、N),但这N个牛不会按照这个顺序排队,给你N-1个数字,表示乱序排队的牛从第二个开始前面比它编号小的牛的个数,根据这N-1个数字,将这乱序的牛的顺序输出。

代码如下:

#include<iostream>

using namespace std ;

const int Max = 8000 ;

struct

{

   int L, R, len ;

}Node[3*Max];

int pre[Max], ans[Max] ;

 

void BuildTree(int root, int L, int R)

{

   Node[root].L = L ;

   Node[root].R = R ;

   Node[root].len = R-L+1 ;

   if(L == R)

       return ;

   BuildTree(2*root, L, (L+R)/2) ;

   BuildTree(2*root+1, (L+R)/2+1, R) ;

}

int Query(int root, int v)

{

    Node[root].len--;

   if(Node[root].L == Node[root].R)

       return Node[root].L ;

   if(Node[2*root].len < v)

       return Query(2*root+1, v - Node[2*root].len) ;

   if(Node[2*root].len >= v)

       return Query(2*root, v) ;

}

int main()

{

   int n, i ;

   scanf("%d", &n) ;

   pre[1] = 0 ;

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

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

   BuildTree(1, 1, n) ;

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

       ans[i] = Query(1, pre[i]+1) ;

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

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

   return 0 ;

}

运用线段树求解,每个结点存区间[L,R]以及长度len。

本题先输入一组乱序的牛的编号顺序,如:1 2 1 0 ,因为第一个牛前不可能会有牛的编号比它的编号小,所以这组编号可以看成:01 2 1 0 , 这组数字正序看我们会一头雾水,不知怎么解决,但倒叙看会有不同的感觉,最后一个数字为0,表示最后一个牛前没有比它小的牛的编号,似乎只有编号为1 的牛才满足这样的条件,仔细想想也是这么回事儿,那我们继续看,倒数第二个数字是1 表示倒数第二个牛前只有1个牛的编号比它小,似乎也只有3号牛才满足条件…… 通过倒叙推理,我们实际上已经从理论上解决了这个问题。所以代码中for(i = n; i >= 1 ;i--)

       ans[i] = Query(1, pre[i]+1) ;通过倒叙给ans数组赋值。

将区间[1,N]建立线段数,区间[1,N]可以看做是牛按顺序排序,数字不仅表示第几个牛,也表示它前面有几个比它编号小。

Main()函数中ans[i] =Query(1, pre[i]+1)。Pre[i]+1可以理解为,因为最前面的牛也有1个比它编号小,就可以和顺序排列的牛所对应,就可以通过Query()得出某个位置的牛实际编号是多少。

0 0
原创粉丝点击