POJ2828

题目大意

插队的问题,每个案例给出n,代表有n个插队的,每个给出p,v,意思是代号为v的人插在了第p个人的后面,问最后的队伍的排列?


倒序处理
初始化将队列中每一个位置设为 1,倒序查找每一个人,二分他的位置,使得他在第v个空位


代码

//线段树二分模板  
#include <iostream>
#include <cstdio>
using namespace std;
const int maxn=200003;
int n,ans[maxn];
struct node{int l,r,sum;}a[maxn<<2];
struct node1{int a,b;}keep[maxn];
void pushup(int x){a[x].sum=a[x<<1].sum+a[x<<1|1].sum;}
void build(int x,int left,int right)
{
	a[x].l=left,a[x].r=right;
	if(left==right) return a[x].sum=1,void();
	int mid=left+right>>1;
	build(x<<1,left,mid),build(x<<1|1,mid+1,right);
	pushup(x);
}
void add(int x,int pos,int num)
{
	if(a[x].l==a[x].r) return a[x].sum=0,ans[a[x].l]=num,void();
	if(pos<=a[x<<1].sum) add(x<<1,pos,num);
	else add(x<<1|1,pos-a[x<<1].sum,num);
	pushup(x);
}
int main()
{
	//freopen("tmp.in","r",stdin);
	while(scanf("%d",&n)!=EOF)
	{
		build(1,1,n);
		for(int i=1;i<=n;++i) scanf("%d%d",&keep[i].a,&keep[i].b);
		for(int i=n;i;--i) add(1,keep[i].a+1,keep[i].b);
		for(int i=1;i<=n;++i) cout<<ans[i]<<' ';
		puts("");
	}
	return 0;
}
/*
cin:
4
0 77
1 51
1 33
2 69
4
0 20523
1 19243
1 3890
0 31492

cout:
77 33 69 51
31492 20523 3890 19243
*/
posted @ 2021-03-15 22:05  wuwendongxi  阅读(70)  评论(0编辑  收藏  举报