//题目的关键就在于查询元素所在的位置
int query(int l,int r,int rt,int p)
{
if(l==r)
{
sum[rt]=0;
return l;
}
int ret;
int m=(l+r)>>1;
if(p<sum[rt<<1]) //与2182 相类似,不过这里只有< 不是<=。要好好想清楚,在这道题目中,你从后往前插,p若是与sum[rt<<1] 相同,说明最开始排队是 p先占了这个位置,后来p被人插队,p必定会往后移动一个位置。所以只能是< 。表达得可能不是很明白,但要仔细想想就懂了
ret=query(l,m,rt<<1,p);
else
ret=query(m+1,r,rt<<1|1,p-sum[rt<<1]);
push_up(rt);
return ret;
}
这道题目与poj 2182 相类似,不过在这道题目中pos[i] =2就表明 该元素在0—n-1 的中的2 的位置。 在2182中的pos 表示他前面有多少只牛,要自加一再来从查询。
这张图片是我的插入过程。
第一次插 2 69
2 不可能小于sum[rt<<1]=2 所以往右边走到2-3
query(rson, 2-sum[rt<<1]) 即query(rson,0);
轻易的就能得到第一个答案。
在2处放69
更新区间。
接着找1 33
由于1< 2 成立,走到0-1;
后来1不可能小于1 ,于是走到了 1. 这里就放33.
更新区间
再找1 51
这是1 不小于1 于是走到了2-3;
query( rson ,1-0) 最后达到3 ,插入51.
最后以此类推在0 处插入77
贴上完整代码
要注意区间的下标0- n-1
#include <stdio.h>
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define N 200005
int sum[N<<2];
int val[N];
int pos[N];
int result[N];
void push_up(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 m=(l+r)>>1;
build(lson);
build(rson);
push_up(rt);
}
int query(int l,int r,int rt,int p)
{ if(l==r)
{ sum[rt]=0;
return l;
}
int m=(l+r)>>1;
int ret;
if(p<sum[rt<<1])
ret=query(lson,p);
else
ret=query(rson,p-sum[rt<<1] );
push_up(rt);
return ret;
}
int main()
{ int n,i;
while(scanf("%d",&n)!=EOF)
{
build(0,n-1,1);
for(i=0;i<n;i++)
scanf("%d%d",&pos[i],&val[i] );
for(i=n-1;i>=0;i--)
result[ query(0,n-1,1,pos[i] ) ]=val[i];
for(i=0;i<n-1;i++)
printf("%d ",result[i]);
printf("%d\n",result[i]);
}
}