题目链接:http://poj.org/problem?id=2828
线段树单点更新问题。
从后往前插入,因为最后一个插入某位置的数是确定的。
之后每个节点用sum记录该区间的空位置数,
如果左区间空位置数比要插入位置大,更新左区间,否则更新右区间,并且pos要减去左区间空位置数。
(感觉想到这一点就会比较容易,否则有一种无从下手的感觉。。。)
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int INF=0x3f3f3f3f; const int maxn=200010; int T,n; int sum[maxn],sequence[maxn]; struct Point{ int pos; int val; }p[maxn]; struct segTree{ int l; int r; int sum; }node[3*maxn]; void PushUp(int id){ node[id].sum=node[id<<1].sum+node[id<<1|1].sum; } void build(int id,int l,int r){ node[id].l=l; node[id].r=r; node[id].sum=r-l+1;//表示该区间空位置数 if(l==r) return ; int mid=(l+r)>>1; build(id<<1,l,mid); build(id<<1|1,mid+1,r); } void Update(int pos,int val,int l,int r,int id){ if(l==r){ sequence[l]=val; node[id].sum=0; return ; } int mid=(l+r)>>1; if(pos<=node[id<<1].sum) Update(pos,val,l,mid,id<<1); else Update(pos-node[id<<1].sum,val,mid+1,r,id<<1|1); PushUp(id); } int main(){ #ifndef ONLINE_JUDGE freopen("test.in","r",stdin); freopen("test.out","w",stdout); #endif while(~scanf("%d",&n)){ build(1,1,n); for(int i=1;i<=n;i++) scanf("%d%d",&p[i].pos,&p[i].val); memset(sum,0,sizeof(sum)); for(int i=n;i>=1;i--) Update(p[i].pos+1,p[i].val,1,n,1); for(int i=1;i<=n;i++) printf("%d%c",sequence[i],i==n?'\n':' '); } return 0; }