题目地址:https://www.acwing.com/problem/content/245/
题目描述:
有n头奶牛,已知它们的身高为 1~n 且各不相同,但不知道每头奶牛的具体身高。
现在这n头奶牛站成一列,已知第i头牛前面有AiAi头牛比它低,求每头奶牛的身高。
输入格式
第1行:输入整数n。
第2..n行:每行输入一个整数AiAi,第i行表示第i头牛前面有AiAi头牛比它低。
(注意:因为第1头牛前面没有牛,所以并没有将它列出)
输出格式
输出包含n行,每行输出一个整数表示牛的身高。
第i行输出第i头牛的身高。
数据范围
1≤n≤1e5
题解:这道题需要从后往前考虑。需要完成两个问题:找到剩余最小的第k个数、删除一个数。本来这是典型的平衡树问题,但是一般而言的平衡树比较难写。而且对于这道题而言,可以使用树状数组+二分来完成。可以让每个a[i]=1,然后查找第一个前缀和大于给出的值,就是当前结果,至于删除一个数,就是让这个数的位置加上-1就可以了。
AC代码:
#include<iostream> #include<cstring> using namespace std; const int N=1e5+10; #define lowbit(x) (x&(-x)) int c[N],n; int b[N]; int a[N]; void add(int x,int d){ while(x<=n){ c[x]+=d; x+=lowbit(x); } } int sum(int x){ int sum=0; while(x>0){ sum+=c[x]; x-=lowbit(x); } return sum; } int main(){ cin>>n; memset(c,0,sizeof(c)); for(int i=2;i<=n;i++) cin>>b[i]; for(int i=1;i<=n;i++) add(i,1); b[1]=0; for(int i=n;i>=1;i--){ int l=1,r=n; while(l<r){ int mid=l+r>>1; if(sum(mid)>b[i]) r=mid; else l=mid+1; } a[i]=r; add(r,-1); } for(int i=1;i<=n;i++) cout<<a[i]<<endl; return 0; }
写于:2020/8/26 23:16