AcWing 244. 谜一样的牛|树状数组

传送门

题目描述

有n头奶牛,已知它们的身高为 1~n 且各不相同,但不知道每头奶牛的具体身高。

现在这n头奶牛站成一列,已知第i头牛前面有Ai头牛比它低,求每头奶牛的身高。

输入格式

第1行:输入整数n。

第2..n行:每行输入一个整数Ai,第i行表示第i头牛前面有Ai头牛比它低。
(注意:因为第1头牛前面没有牛,所以并没有将它列出)

输出格式

输出包含n行,每行输出一个整数表示牛的身高。

第i行输出第i头牛的身高。

数据范围

1n105

输入样例:

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
",ans[i]);
    return 0;
}
View Code

  

原文地址:https://www.cnblogs.com/l999q/p/11348580.html