poj 2828 (线段树)

//思路:从最后一个人往前插,这样pos的意义就变成了,前面有多少个空位。
//线段树上每个节点中存储的是当前时刻,该区间有多少空位。
//如果某个人插入到pos[i],则找第pos[i]个空位置插入即可
#include <iostream>
using namespace std;

struct node{
	int from, to;
	int cap;
};

const int MAX_NUM = 200002;
node line[3*MAX_NUM];
int pos[MAX_NUM], val[MAX_NUM], ans[MAX_NUM];
int n;

//建树
void build_tree(int left, int right, int c)
{
	line[c].from = left;
	line[c].to = right;
	line[c].cap = right - left + 1;
	if (left == right) return;
	int mid = (left + right) / 2;
	build_tree(left, mid, c<<1);
	build_tree(mid+1, right, (c<<1)+1);
}

int insert(int pos)
{
	int c = 1;
	while (line[c].from != line[c].to){
		line[c].cap--; //当前节点容量减1
		//如果左半边容量足够大,则递归进入左半边
		if (line[c<<1].cap >= pos){
			c <<= 1;
		}
		else{
			pos -= line[c<<1].cap;
			c = ((c<<1)+1);
		}
	}
	//递归结束,找到插入的位置
	line[c].cap--;
	return line[c].from;
}

int main()
{
	int i;
	while (scanf("%d", &n) != EOF){
		build_tree(1, n, 1);
		for (i = 0; i < n; ++i)
			scanf("%d%d", &pos[i], &val[i]);
		for (i = n-1; i >= 0; --i)
			ans[insert(pos[i]+1)] = val[i];
		for (i = 1; i < n; ++i)
			printf("%d ", ans[i]);
		printf("%d\n", ans[i]);
	}
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值