这道题是从最后一个数开始建立线段树,区间存储的范围是该区间有多少个空位剩余,对于最后一个插入的数,它肯定和其插入的位置一致,例如对于测试数据的第一组,69插入2这个位置,是肯定的,它将前面占有2位置的数向后面推,同理对于倒数第二个数,占有1这个位置,如果前面有数占有1这个位置,此时前面的必定是向后面推。假设P为插入的位置,因次每次查看左区间有没有大于等于p的空位,如果有则搜索,否者搜索右孩子。
#include<cstdio> #include<cstdlib> #include<cmath> #include<cstring> #define MAXN 200005 int seg_tree[MAXN<<2]; void build_tree(int l,int r,int id); void push_up_tree(int id); void update_tree(int left,int right,int l,int r,int id); int ans[MAXN],cur; struct Node { int i; int num; }; Node temp[MAXN]; int main() { int n,i,j,k; while(scanf("%d",&n)==1) { build_tree(1,n,1); for(i=1;i<=n;i++) {scanf("%d%d",&temp[i].i,&temp[i].num);} for(i=n;i>0;i--) { cur=temp[i].num; update_tree(temp[i].i+1,n,1,n,1); } for(i=1;i<=n;i++) {if(i-1) printf(" "); printf("%d",ans[i]); } printf("\n"); } } void build_tree(int l,int r,int id) { if(l==r) { seg_tree[id]=1; return ; } int m=(l+r)>>1; build_tree(l,m,id<<1); build_tree(m+1,r,id<<1|1); push_up_tree(id); } void push_up_tree(int id) { seg_tree[id]=seg_tree[id<<1]+seg_tree[id<<1|1]; } void update_tree(int left,int right,int l,int r,int id) { if(l==r) { seg_tree[id]--; ans[l]=cur; return ; } int m=(l+r)>>1; if(left<=seg_tree[id<<1]) update_tree(left,right,l,m,id<<1); else { left-=seg_tree[id<<1]; update_tree(left,right,m+1,r,id<<1|1); } push_up_tree(id); }