这题没思路,看别人题解
由于最后一个人插进来后他的位置肯定是固定的 我们就可以倒着来插
用sum[]数组表示改线段空位置的个数,满足 pos<=sum[rt<<1](即左儿子的空位多于插入数的位置序号)就访问左儿子,否则访问右儿子
(访问右节点的时候注意pos要修改,改为pos-sum[rt],即整个线段的第pos个空位,在下一个右儿子那的第pos-sum[rt]个空位)。
Problem: 2828 User: shu_dayang Memory: 4536K Time: 1500MS Language: C++ Result: Accepted #include<iostream> #include<cstdio> #include<cstring> #define MID(a,b) ((a + b) >> 1) using namespace std; const int MAXN = 200010; int sum[MAXN << 2],p[MAXN],pos[MAXN],val[MAXN]; void PushUp(int rt) { sum[rt] = sum[rt << 1] + sum[(rt << 1) + 1]; } void build(int l, int r, int rt) { if(l == r) { sum[rt] = 1; return; } int mid = MID(l, r); build(l, mid, rt << 1); build(mid + 1, r, (rt << 1) + 1); PushUp(rt); } void update(int pos,int val, int l, int r, int rt) { if(l == r) { p[l] = val; sum[rt] --; return; } int mid = MID(l, r); if(pos <= sum[rt << 1]) update(pos, val, l, mid, rt << 1); else update(pos - sum[rt << 1], val, mid + 1, r, (rt << 1) + 1); PushUp(rt); } int main() { int n,i; while(~scanf("%d",&n)) { build(1,n,1); for(i = 0; i < n; i++) scanf("%d%d",&pos[i],&val[i]); for(i = n - 1; i >= 0; i--) update(pos[i] + 1,val[i],1,n,1); for(i = 1; i< n ; i++) printf("%d ",p[i]); printf("%d\n",p[i]); } }
原文:http://www.cnblogs.com/yong-hua/p/4658498.html