受虐的晚上==
感谢大神的博客http://www.cnblogs.com/crazyapple/p/3233149.html
题意:第一行是整数N,代表队伍一共有N个人。然后N行,第一个数字代表N进队的时候前边有几个人,第二个数字是第I个人的标识符。
求最后队伍的顺序,一次输出标识符。
思路:思路是大神的思路,我又抄袭真是可耻==
第一步是倒序的思想,最后一个人前边应该有几个空位置,倒数第二个人有几个空位置依次确定。
第二步,根据线段树的思想,记录该线段中有几个空位置。(屌丝一开始的思路是记录该线段之前的空位置的个数,在分治的时候需要处理的线段太多,超时==)
第三步,确定每一个人最终的位置,输出。(思想是每个人都要更新一下父亲线段的空位置数,同时判断父亲线段左儿子的空位置数,如果左儿子的空位置数大于我们要找的位置数,在左儿子中找,否则减掉左儿子的位置数之后在右儿子中找)
#include<iostream> #include<stdio.h> #include<string.h> using namespace std; struct tr { int l,r,pos; }; tr me[200000*3]; int shun[200001]; short his[200001]; short ans[200001]; void build(int s,int e,int k) { me[k].l=s; me[k].r=e; me[k].pos=e-s+1; if(s==e) return; int m=(s+e)>>1; build(s,m,k<<1); build(m+1,e,k<<1|1); } void update(int i,int k,int c) { me[k].pos--; if(me[k].r==me[k].l) { ans[me[k].r]=his[i]; return; } if(me[k<<1].pos>c) update(i,k<<1,c); else update(i,k<<1|1,c-me[k<<1].pos); } int main() { short tmp; int n,w,i; while(scanf("%d",&n)!=EOF) { memset(ans,-1,sizeof(ans)); build(1,n,1); for(i=1;i<=n;i++) { scanf("%d%d",&shun[i],&his[i]); } for(i=n;i>=1;i--) { update(i,1,shun[i]); } for(i=1;i<=n;i++) printf("%d ",ans[i]); printf("\n"); } return 0; }