AcWing 244. 谜一样的牛|树状数组
题目描述
有n头奶牛,已知它们的身高为 1~n 且各不相同,但不知道每头奶牛的具体身高。
现在这n头奶牛站成一列,已知第i头牛前面有Ai头牛比它低,求每头奶牛的身高。
输入格式
第1行:输入整数n。
第2..n行:每行输入一个整数Ai,第i行表示第i头牛前面有Ai头牛比它低。
(注意:因为第1头牛前面没有牛,所以并没有将它列出)
输出格式
输出包含n行,每行输出一个整数表示牛的身高。
第i行输出第i头牛的身高。
数据范围
1≤n≤105
输入样例:
5
1
2
1
0
输出样例:
2
4
5
3
1
题解:如果最后一头牛前面有An头牛比它矮显然它的身高为An+1。如果倒数第二头牛前面有An-1头牛比它矮的话它的身高为1~n里面除了最后一头牛的身高以外第An-1+1大的值。以此类推我们知道第i头牛它的身高是1~n中除了第i+1到n以外的值中第Ai+1大的值。
我们可以建立一个长度为n的01序列,从n到1倒序找出第Ai+1个1的位置作为第i头牛的身高,然后将这个位置的1变为0。
我们可以用树状数组来维护前x个中有多少个1,先将每个位置都add(1),如果数量和Ai+1一样那么这个x就是第i头牛的身高,再将这个位置减去add(-1)。
代码:
#include <bits/stdc++.h> #define ll long long using namespace std; const int INF = 2e9; const int N = 1e5 + 10; int a[N],sum[N],ans[N]; int lowbit(int x) { return x&(-x);} void add(int x,int y) { for (;x<N;x+=lowbit(x)) sum[x]+=y; } int query(int x) { int ans = 0; for (;x>0;x-=lowbit(x)) ans += sum[x]; return ans; } int main() { int n; scanf("%d",&n); a[1] = 1; add(1,1); for (int i = 2; i <= n; i++) { scanf("%d",&a[i]); a[i]++; add(i,1); } for (int i = n; i > 0; --i) { int l = 1,r = n,mid; while (l<r) { mid = (l+r)/2; if (query(mid) >= a[i]) r = mid; else l = mid+1; } ans[i] = l; add(l,-1); } for (int i = 1; i <= n; i++) printf("%d\n",ans[i]); return 0; }