[poj2182] 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.
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.
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.
Sample Input
5
1
2
1
0
Sample Output
2
4
5
3
1
题目大意
1 ~ n 中的 n 个数以某一个顺序排列,给出这个排列中对于于第 2 到第 n 个数,在它前面并且比它小的数字个数。让你输出这个排列。
题解
这道题比较基本,和poj2828很相似,我就直接用那道题的代码改了。用线段树来维护每个数是否出现过。
从后往前更新。
例如样例 (0), 1, 2, 1, 0;
先更新第 5 个位置,查询第 1 个还没出现过的数字,得到 1,将其赋值为 0 (已出现过),更新ans[5] = 1;
然后更新第 4 个位置,查询第 2 个没出现过的数字,得到 3 ,更新ans[4] = 3;
......剩下的应该知道怎么做了吧,线段树中的值表示该区间中没有出现过的数的个数。
代码
#include <iostream>
using namespace std;
#define pushup(u) {sum[u] = sum[u<<1] + sum[u<<1|1];}
#define ls u<<1,l,mid
#define rs u<<1|1,mid+1,r
const int maxn = 2e5 + 5;
int sum[maxn << 2];
int ans[maxn];
int pos[maxn];
void build(int u,int l,int r) {
sum[u] = r - l + 1;
if(l == r)return;
int mid = (l + r) >> 1;
build(ls);
build(rs);
}
int update(int u,int l,int r,int x,int a) {
if(l == r){
sum[u] = 0;
return l;
}
int res;
int mid = (l + r) >> 1;
if(sum[u << 1] >= x)res = update(ls,x,a);
else res = update(rs,x - sum[u<<1],a);
pushup(u);
return res;
}
int main() {
ios::sync_with_stdio(false); cin.tie(0);
int n;
while(cin >> n) {
build(1,1,n);
pos[1] = 0;
for(int i = 2;i <= n;i++) {
cin >> pos[i];
}
for(int i = n;i > 0;i--) {
ans[i] = update(1,1,n,pos[i] + 1,i);
}
for(int i = 1;i <= n;i++) {
cout << ans[i] << endl;
}
}
return 0;
}