Lost Cows poj2182(树状数组+二分)

题干:
有n头奶牛(n<=105),已知它们的身高为1~n且各不相同,但不知道每头奶牛的具体身高。
现在这n头奶牛站成一列,已知第i头奶牛前面有Ai头比它低,求每头奶牛的身高。
输入:
第1行,一个整数n,牛的头数
第2~n行,每行一个数,表示前面有几头牛比它低。
输出
n行,每行一个数,代表n头牛的高度

样例输入
5
1
2
1
0
样例输出
2
4
5
3
1

算法分析:
如果最后一头奶牛前面有An头牛比它低,那么显然它的身高就是
Hn=An+1。
这步如果不明白,我们可以想象一下,n头牛的身高就是1 ~ n之间这些数,而且身高各不相同。也就是n头牛从1~n中认领一个数字当它们的身高。
如果第n头奶牛前面有An头比它低,第n头奶牛是第An+1高,前面比它低的奶牛,只能从1~An中的数字认领自己的身高。
如果倒数第二头奶牛前面有An-1头奶牛比它低。那么:
1、若An-1<An,则它的身高Hn-1=An-1+1
2、若An-1>=An,则它的身高Hn-1=An-1+1+1

在扫描倒数第二头牛时,第n头牛已经用去一个数了,看下图

在这里插入图片描述
以此类推,如果第k头牛前面有Ak头比它低,那么它的身高Hk就是数值1~ n 中第Ak+1小的没有在{Hk+1,Hk+2,…Hn}中出现过的数。

具体来说,我们建立一个长度为n的01序列b,起初全部为1,表示这n个数都没被奶牛认领。然后,从n到1倒序扫描每个Ai,对每个Ai执行以下两个操作:
1、查询序列B中第Ai+1个1在什么位置,这个位置就是第i头奶牛的身高Hi。
2、把b[hi]-1(1变为0)
完整代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int a[10000],c[10000],h[10000],n;

int ask(int x)
{
	int ans=0;
	for(;x;x-=x&-x) ans+=c[x];
	return ans;
}

void add(int x,int y)
{
	for(;x<=n;x+=x&-x) c[x]+=y;
}

int query(int x)
{
	int l=1,r=n;
	while(l<r)
	{
		int mid=(l+r)/2;
		if(ask(mid)<x) l=mid+1; else r=mid;
	}
	return l;
}

int main()
{
	cin>>n;
	for(int i=2;i<=n;i++) scanf("%d",&a[i]);
	memset(c,0,sizeof(c));
	for(int i=1;i<=n;i++) add(i,1);
	for(int i=n;i;i--)
	{
	    h[i]=query(a[i]+1);
	    add(h[i],-1);
	}
	for(int i=1;i<=n;i++) cout<<h[i]<<endl;
	
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值