标签:
这题没思路,看别人题解
由于最后一个人插进来后他的位置肯定是固定的 我们就可以倒着来插
用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