倒着考虑,如果最后一只牛的前面有x只比它小,那么它就是第x+1只牛,从序列中去掉它。对倒数第二只牛来说也同理。可以用树状数组来维护前缀和,一开始每个位置都是1,求出结果的牛从树状数组中删掉(update成0),即可获得答案。
1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 using namespace std; 5 6 const int N = 8001; 7 int c[N]; 8 int r[N]; 9 int ans[N]; 10 int n; 11 12 int lb( int i ) 13 { 14 return i & -i; 15 } 16 17 void update( int i, int v ) 18 { 19 while ( i <= n ) 20 { 21 c[i] += v; 22 i += lb(i); 23 } 24 } 25 26 int kth( int k ) 27 { 28 int ans = 0, cnt = 0; 29 for ( int i = 12; i >= 0; i-- ) 30 { 31 ans += ( 1 << i ); 32 if ( ans >= n || cnt + c[ans] >= k ) 33 { 34 ans -= ( 1 << i ); 35 } 36 else 37 { 38 cnt += c[ans]; 39 } 40 } 41 return ans + 1; 42 } 43 44 int main () 45 { 46 while ( scanf("%d", &n) != EOF ) 47 { 48 memset( c, 0, sizeof(c) ); 49 for ( int i = 1; i <= n; i++ ) 50 { 51 update( i, 1 ); 52 } 53 r[1] = 1; 54 for ( int i = 2; i <= n; i++ ) 55 { 56 scanf("%d", &r[i]); 57 r[i]++; 58 } 59 for ( int i = n; i >= 1; i-- ) 60 { 61 ans[i] = kth( r[i] ); 62 update( ans[i], -1 ); 63 } 64 for ( int i = 1; i <= n; i++ ) 65 { 66 printf("%d\n", ans[i]); 67 } 68 } 69 return 0; 70 }
时间: 2024-10-22 15:36:47