POJ 2182 / HDU 2711 Lost Cows(平衡树)
Description
N (2 <= N <= 8,000) cows have unique brands in the range 1..N. In a spectacular display of poor judgment, they visited the neighborhood 'watering hole' and drank a few too many beers before dinner. When it was time to line up for their evening meal, they did not line up in the required ascending numerical order of their brands.
Regrettably, FJ does not have a way to sort them. Furthermore, he's not very good at observing problems. Instead of writing down each cow's brand, he determined a rather silly statistic: For each cow in line, he knows the number of cows that precede that cow in line that do, in fact, have smaller brands than that cow.
Given this data, tell FJ the exact ordering of the cows.
Regrettably, FJ does not have a way to sort them. Furthermore, he's not very good at observing problems. Instead of writing down each cow's brand, he determined a rather silly statistic: For each cow in line, he knows the number of cows that precede that cow in line that do, in fact, have smaller brands than 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 given cow in line and have brands smaller than that cow. Of course, no cows precede the first cow in line, so she is not listed. Line 2 of the input describes the number of preceding cows whose brands are smaller than the cow in slot #2; line 3 describes the number of preceding cows whose brands are smaller than the cow in slot #3; and so on.
* Lines 2..N: These N-1 lines describe the number of cows that precede a given cow in line and have brands smaller than that cow. Of course, no cows precede the first cow in line, so she is not listed. Line 2 of the input describes the number of preceding cows whose brands are smaller than the cow in slot #2; line 3 describes the number of preceding cows whose brands are smaller than the cow in slot #3; and so on.
Output
* Lines 1..N: Each of the N lines of output tells the brand of a cow in line. Line #1 of the output tells the brand of the first cow in line; line 2 tells the brand of the second cow; and so on.
题目大意:有n只牛,每只牛有一个1~n的编号,每只牛知道前面有多少只牛编号比它小,问每只牛的编号是啥。
思路:这题思路很多,这里采取平衡树的做法(O(n²)也是能AC的o(╯□╰)o)。先把1~n插入平衡树,从后往前扫,如果牛 i 前面有 pre[i] 只牛编号比它小,那么他就是还未被删掉的编号的第 pre[i] + 1个,然后删掉这个编号。
代码(POJ 141MS):
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 using namespace std; 6 7 const int MAXN = 8010; 8 9 int key[MAXN], weight[MAXN], child[MAXN][2], size[MAXN]; 10 int stk[MAXN], top, cnt; 11 12 inline int new_node(int k) { 13 int x = (top ? stk[top--] : ++cnt); 14 key[x] = k; 15 size[x] = 1; 16 weight[x] = rand(); 17 child[x][0] = child[x][1] = 0; 18 return x; 19 } 20 21 inline void update(int &x) { 22 size[x] = size[child[x][0]] + size[child[x][1]] + 1; 23 } 24 25 inline void rotate(int &x, int t) { 26 int y = child[x][t]; 27 child[x][t] = child[y][t ^ 1]; 28 child[y][t ^ 1] = x; 29 update(x); update(y); 30 x = y; 31 } 32 33 void insert(int &x, int k) { 34 if(x == 0) x = new_node(k); 35 else { 36 int t = (key[x] < k); 37 insert(child[x][t], k); 38 if(weight[child[x][t]] < weight[x]) rotate(x, t); 39 } 40 update(x); 41 } 42 43 void remove(int &x, int k) { 44 if(key[x] == k) { 45 if(child[x][0] && child[x][1]) { 46 int t = weight[child[x][0]] < weight[child[x][1]]; 47 rotate(x, t); remove(child[x][t ^ 1], k); 48 } 49 else { 50 stk[++top] = x; 51 x = child[x][0] + child[x][1]; 52 } 53 } 54 else remove(child[x][key[x] < k], k); 55 if(x > 0) update(x); 56 } 57 58 int kth(int &x, int k) { 59 if(x == 0 || k <= 0 || k > size[x]) return 0; 60 int s = 0; 61 if(child[x][0]) s = size[child[x][0]]; 62 if(k == s + 1) return key[x]; 63 if(k <= s) return kth(child[x][0], k); 64 return kth(child[x][1], k - s - 1); 65 } 66 67 int ans[MAXN], pre[MAXN]; 68 69 int main() { 70 int n; 71 scanf("%d", &n); 72 pre[1] = 0; 73 for(int i = 2; i <= n; ++i) scanf("%d", &pre[i]); 74 int root = new_node(1); 75 for(int i = 2; i <= n; ++i) insert(root, i); 76 for(int i = n; i > 0; --i) { 77 int t = kth(root, pre[i] + 1); 78 ans[i] = t; 79 remove(root, t); 80 } 81 for(int i = 1; i <= n; ++i) 82 printf("%d\n", ans[i]); 83 }
使用pb_ds库。使用方法可以参考WC2015的论文《C++的pb_ds库在OI中的应用》。
注意:这题在HDU上是多组数据,但是题目没有写清楚。
代码(31MS):
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 #include <ext/pb_ds/assoc_container.hpp> 6 #include <ext/pb_ds/tree_policy.hpp> 7 8 const int MAXN = 8010; 9 10 __gnu_pbds::tree<int, __gnu_pbds::null_type, std::less<int>, __gnu_pbds::rb_tree_tag, __gnu_pbds::tree_order_statistics_node_update> tree; 11 int ans[MAXN], pre[MAXN]; 12 int n; 13 14 int main() { 15 while(scanf("%d", &n) != EOF) { 16 for(int i = 2; i <= n; ++i) scanf("%d", &pre[i]); 17 tree.clear(); 18 for(int i = 1; i <= n; ++i) 19 tree.insert(i); 20 for(int i = n; i > 0; --i) { 21 int t = *tree.find_by_order(pre[i]); 22 ans[i] = t; 23 tree.erase(t); 24 } 25 for(int i = 1; i <= n; ++i) 26 printf("%d\n", ans[i]); 27 } 28 }