poj 2828 Buy Tickets

题意: 插队问题,有n个人,每个人都有一个val,第i个人插在第j(0 <= j < i)个人后面,问最后队列中从前到后的val。
思路: 线段树的单点修改。从后往前看,当第i人插到第j个人后面时,他的前面必然有 j个空位。所以当他开始插队时,就可以利用线段树找到要查对的位置。

#include <iostream>
#include <cstdio>

using namespace std;
typedef long long ll;
const int N = 200010;
#define ls(x) (x<<1)
#define rs(x) (x<<1|1)
int n, m;
int sgt[N<<2], ans[N];
struct node{
	int id, val;
}a[N];
inline void pushup(int x)
{
	sgt[x] = sgt[ls(x)] + sgt[rs(x)];
}
void build(int x, int l, int r)
{
	if(l > r) return ;
	if(l == r) {
		sgt[x] = 1;
		return ;
	}
	int mid = l + r >> 1;
	build(ls(x), l, mid);
	build(rs(x), mid+1, r);
	pushup(x);
}
inline void update(int x, int l, int r, int k, int v)
{
	int mid = l + r >> 1;
	if(l == r) {
		ans[l] = v;
		sgt[x] --;
		return ;
	}
	if(sgt[ls(x)] >= k) update(ls(x), l, mid, k, v);
	else update(rs(x), mid+1, r, k - sgt[ls(x)], v);
	pushup(x);
}
int main()
{
	while(scanf("%d", &n) != EOF) {
		build(1, 1, n);
		for(int i = 1;i <= n; ++ i)
		scanf("%d%d", &a[i].id, &a[i].val);
		for(int i = n;i >= 1; -- i) {
			update(1, 1, n, a[i].id + 1, a[i].val);
		}
		for(int i = 1;i <= n; ++ i)
		printf("%d ", ans[i]);
		puts("");
	}
} 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值