poj2828 Buy Tickets
线段树的基本题。题意大概是:人们依次来排队并插队,按人到来的顺序给出每个人插队的位置(插在第几个人后面),并告知每个人的id号,输出最终的情况。
与poj2182有点像,只不过将数字的大小改成插入的先后顺序。
#include<iostream> #include<stdio.h> #define MAXD 200001 using namespace std; int N,P[MAXD],V[MAXD],f[MAXD],sum[MAXD*3],D,re[MAXD]; void init() { for(D=1;D<N+2;D<<=1); int i; for(i=1;i<=N;i++) sum[D+i]=1; for(i=D-1;i;i--) sum[i]=sum[i<<1]+sum[i<<1|1]; } int query(int k) { int i; for(i=1;i<D;) { if(sum[i<<1]>=k) i=i<<1; else k-=sum[i<<1],i=i<<1|1; } return i-D; } void update(int k) { k+=D; sum[k]=0; for(;k^1;k>>=1) sum[k>>1]=sum[k]+sum[k^1]; } int main() { //freopen("test.txt","r",stdin); while(~scanf("%d",&N)) { int i; for(i=1;i<=N;i++) scanf("%d%d",&P[i],&V[i]); init(); for(i=N;i>=1;i--) { f[i]=query(P[i]+1); update(f[i]); } for(i=1;i<=N;i++) { re[f[i]]=i; } for(i=1;i<=N;i++) printf(i==N?"%d\n":"%d ",V[re[i]]); } return 0; }