Lost Cows[题解]

题目大意

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

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

解题思路

当我们看到这个题目第一眼想到的肯定是从后往前扫,因为最后一个奶牛的排名是可以直接确定的,就是\(a_n+1\),因此我们是不是可以借着后面奶牛的排名,试着推出前一个奶牛的排名?

通过观察我们可以发现对于一个奶牛\(i\)\(a_i+1\)即为奶牛\(i\)在前\(i\)头奶牛当中的排名,由于我们后面奶牛的排名是已经求出来的了,若后面有些奶牛的排名比\(a_i+1\)要小那么奶牛\(i\)的排名肯定比\(a_i+1\)要大,那我们能不能通过求后面奶牛中排名小于等于\(a_i\)的有多少个再加上\(a_i+1\)呢?

答案是不能的,因为当我们尝试升高排名时,后面奶牛小于等于这个排名的奶牛个数有可能是在增大的,因此并不能用简单的前缀和求出,但是最后的排名\(rank_i\)一定满足\(rank_i=a_i+sum_j[rank_j<=rank_i]+1\),然后我们发现当\(rank_i\)增大的时候,后面这一坨要么不变,要么加\(1\),所以这玩意是单调不降的,对于一个大于\(rank_i\)的值也一定满足这个条件,一个小于\(rank_i\)的值,一定不满足这个条件,因为既然我比真实排名要小这个排名上一定有奶牛的,要么被记录在\(a_i\)中,要么被记录在\(sum_j\)中,而我们的答案又有\(+1\)的限制,所以一定会造成这个排名不满足条件

这本质上就是在找第一个排名空缺位置的奶牛,因此答案是单调的,可以用二分来求,再用树状数组维护排名前缀和就好啦,时间复杂度\(O(nlog^{2}n)\)

code

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10; 
int n,c[N],a[N],ans[N];
inline int lowbit(int x){return x&(-x);}
void add(int x,int val){while(x<=n)c[x]+=val,x+=lowbit(x);}
int sum(int x){int ans=0;while(x)ans+=c[x],x-=lowbit(x);return ans;} 
signed main() {
	ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
	cin>>n;
	for(int i=2;i<=n;i++) cin>>a[i];
	for(int i=n;i>=1;i--) {
		int l=1,r=n,t=0;
		while(l<=r) {
			int mid=(l+r)>>1;
			if(a[i]+1+sum(mid)<=mid) r=mid-1,t=mid;
			else l=mid+1;
		}
		ans[i]=t;
		add(t,1);
	}
	for(int i=1;i<=n;i++) cout<<ans[i]<<"\n";
	return 0;
} 
posted @ 2026-08-15 07:47  技技技技技  阅读(4)  评论(0)    收藏  举报