大意:排队买票问题,后面来的总是把原来的人替换掉,并且使得原来的人往后移,让你顺序输出他们代表的编号,用线段树来记录空格数。
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int MAX = 200005; int p[MAX],va[MAX << 2], d[MAX],sum[MAX];//va储存每两个点之间空格的个数 void build(int n, int l, int r){ va[n] = r - l + 1; if( l == r){ return ; } int mid = ( l + r ) >> 1; build(n << 1, l, mid); build(n << 1|1, mid + 1,r); } int update(int ps ,int n, int l, int r) { va[n]--;//空格数减一 if(l == r){ return l; } int mid = ( l + r) >> 1; if( ps <= va[n<<1]){//如果左子树的空格大于他的下标,说明能放下,就跟新 update(ps, n << 1, l ,mid); } else { ps -= va[n << 1];//否则放到右子树上 update(ps,n << 1|1, mid + 1,r); } } int main() { int n; while(~scanf("%d",&n)){ build( 1,1,n); for(int i = 1; i <= n; i++) scanf("%d%d",&p[i],&d[i]); for(int i = n; i >= 1 ; i--){ int id = update(p[i] + 1, 1, 1, n); sum[id] = d[i]; } for(int i = 1; i < n ; i++) printf("%d ",sum[i]); printf("%d ",sum[n]); } return 0; }