题意:夜里排队买车票,每个人都有自己的id号。排队买票时会插队,输入n对数字,每对包括了他想插入的位子,和自己的id号,后插入的人会把先插入的人挤下去
做法:把先到的人挤下去真心难模拟,那么就倒过来思考。逆序查找序列对,后查到的要往后排,这个思想我以后要记住了
然后建立树时,每个节点的值为当前的空余数,然后就可以模拟了,模拟的时候要小心...
#include<cstdio> #include<cstring> #define left l,m,x<<1 #define right m+1,r,x<<1|1 #define LMT 200002 int have[LMT<<2],val[LMT],ps[LMT],vl[LMT]; int id; void build(int l,int r,int x) { have[x]=r-l+1; if(l==r)return; int m=(l+r)>>1; build(left); build(right); } void update(int p,int l,int r,int x) { if(l==r) { have[x]--; id=l; return ; } int m=(l+r)>>1; if(p+1<=have[x<<1])update(p,left); else { p-=have[x<<1]; update(p,right); } have[x]=have[x<<1]+have[x<<1|1]; } int main(void) { int n; while(~scanf("%d",&n)) { build(0,n-1,1); for(int i=0;i<n;i++) scanf("%d%d",&ps[i],&vl[i]); for(int i=n-1;i>=0;i--) { update(ps[i],0,n-1,1); val[id]=vl[i]; } for(int i=0;i<n;i++) printf("%d ",val[i]); printf("\n"); } return 0; }