POJ 2828 Buy Tickets
题意: 有N 个人站队,告诉每个人想插队的位置,要求确定最终的站队位置。
分析: 越往后插队的人位置越固定,因此可以从后向前插入,每个人插入的位置为从第1 个位置起的第 pos+1 空位置。
用sum[i] 表示 I 区间的人数之和,用线段树维护即可。
#include<stdio.h> #include<string.h> #define clr(x)memset(x,0,sizeof(x)) #define maxn 200005 struct P { int pos,val; }q[maxn]; int sum[maxn<<3]; int va[maxn<<3]; void creat(int l,int r,int rt) { if(l==r) { sum[rt]=1; return; } int m=(l+r)>>1; creat(l,m,rt<<1); creat(m+1,r,rt<<1|1); sum[rt]=sum[rt<<1]+sum[rt<<1|1]; } void update(int pos,int l,int r,int rt,int v) { if(l==r){ va[l]=v; sum[rt]=0; return; } int m=(l+r)>>1; if(sum[rt<<1]>=pos) update(pos,l,m,rt<<1,v); else update(pos-sum[rt<<1],m+1,r,rt<<1|1,v); sum[rt]=sum[rt<<1]+sum[rt<<1|1]; } int main() { int n,i; while(scanf("%d",&n)!=EOF) { for(i=0;i<n;i++) scanf("%d%d",&q[i].pos,&q[i].val); creat(1,n,1); for(i=n-1;i>=0;i--) update(q[i].pos+1,1,n,1,q[i].val); for(i=1;i<=n;i++) printf("%d%c",va[i],i==n?'\n':' '); } return 0; }