poj 2182 树状数组(给牛排序)

题意:有n头牛从1-n标号。现在给出n-1个数,表示第i头牛前面比它序号小的牛的个数。根据此还原牛的原始排序。

思路:从最后向前扫面序列。每次对于未确定的最后一个数来说是可以根据它前面有多少数字比它小以及之前确定的数字(在它后面的数字)而确定它是几的。二分查找当前位置填几,设这个数字为a,应满足树状数组求和结果sum(a),即后面已经填好的比a小的个数,加上f[i],即前面比a小的个数,等于a-1。猜大了则结果大于a-1,猜小了则小于。找到后把树状数组第a位标1。时间复杂度为O((logn)^2 * n)。二分的地方还是不明白。(参考http://www.cnblogs.com/rainydays/archive/2011/06/04/2072849.html)

#include <stdio.h>
#include <string.h>
#define N 8005
int a[N],tree[N],res[N];
int n;
int lowbit(int x){
	return x&(-x);
}
void add(int x){
	int i;
	for(i = x;i<=n;i+=lowbit(i))
		tree[i] ++;
}
int sum(int x){
	int i,res=0;
	for(i = x;i>0;i-=lowbit(i))
		res += tree[i];
	return res;
}
int bisearch(int x){
	int low,high,mid,temp;
	low = 1,high = n;
	while(low < high){
		mid = (low+high)>>1;
		temp = sum(mid) + x;
		if(temp <= mid)
			high = mid;
		else
			low = mid+1;
	}
	return low;
}
int main(){
	freopen("a.txt","r",stdin);
	while(scanf("%d",&n)!=EOF){
		int i,j;
		memset(tree,0,sizeof(tree));
		memset(a,0,sizeof(a));
		for(i = 1;i<n;i++)
			scanf("%d",&a[i]);
		for(i = n-1;i>=0;i--){
			j = bisearch(a[i]+1);
			res[i] = j;
			add(j);
		}
		for(i = 0;i<n;i++)
			printf("%d\n",res[i]);
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值