题意描述:有N个人排队,每一个人都有一个val来对应,每一个后来人都会插入当前队伍的某一个位置pos。要求把队伍最后的状态输出。
分析:倒着考虑。最后一个人前面有pos[i]个人,就留pos[i]个空位,把这个人放在第pos[i]+1个空位上。用线段树,附加值为区间内空位的个数。
考虑了一下用树状数组变形能不能做,结果应该是不能。
code:
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
using namespace std;
const int maxn=200000+10;
int _sum[maxn*4];
int ans[maxn],a[maxn],pos[maxn],val[maxn];
void build(int o,int l,int r){
if(l==r) _sum[o]=1;
else{
int mid=l+(r-l)/2;
build(o*2,l,mid);
build(o*2+1,mid+1,r);
_sum[o]=_sum[o*2]+_sum[o*2+1];
}
}
void add(int p,int v,int o,int l,int r){
_sum[o]=_sum[o]+v;
if(r>l){
int mid=l+(r-l)/2;
if(p<=mid) add(p,v,o*2,l,mid);
else add(p,v,o*2+1,mid+1,r);
}
}
int query(int x,int pre,int o,int l,int r){
if(l==r) return l;
else{
int mid=l+(r-l)/2;
if(x<=pre+_sum[o*2])return query(x,pre,o*2,l,mid);
else return query(x,pre+_sum[o*2],o*2+1,mid+1,r);
}
}
int main(){
int n;
while(scanf("%d",&n)==1){
build(1,1,n);
for(int i=0;i<n;i++)
scanf("%d%d",&pos[i],&val[i]);
for(int i=n-1;i>=0;i--){
int position=query(pos[i]+1,0,1,1,n);
ans[position]=val[i];
add(position,-1,1,1,n);
}
for(int i=1;i<=n;i++) printf("%d ",ans[i]);
printf("\n");
}
return 0;
}