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
*/