poj 2828【线段树 单点更新】
还是弱啊。思维是个好东西。。。
刚开始想来想去用线段树存人的话不仅超时,而且存不下。。。居然是存空位!
sum[]数组存这个序列空位个数,然后逆序遍历。逆序好理解,毕竟最后一个人插进来位置已经可以确定了,前面的位置就根据他来更新。
1 #include<iostream> 2 #include<cstdio> 3 #define mid int m=(l+r)>>1 4 #define lson l,m,rt<<1 5 #define rson m+1,r,rt<<1|1 6 using namespace std; 7 const int maxn=200005; 8 int sum[maxn<<2],ans[maxn<<2]; 9 int N,p[maxn],v[maxn]; 10 11 12 void Build(int l,int r,int rt)//建树存空位 13 { 14 sum[rt]=r-l+1;//初始建树时线段对应的空位数就是线段长度(点看成长度为1的线段) 15 if(l==r) return; 16 mid; 17 Build(lson); 18 Build(rson); 19 } 20 21 void PushUp(int rt) 22 { 23 sum[rt]=sum[rt<<1]+sum[rt<<1|1]; 24 } 25 26 void Update(int pos,int val,int l,int r,int rt) 27 { 28 if(l==r){ 29 ans[l]=val;//递归到节点,用ans[]数组记录第l个人的val值。 30 sum[rt]--;//空位数减1 31 return; 32 } 33 mid; 34 if(pos<=sum[rt<<1]) Update(pos,val,lson);//如果当前节点左孩子的空位数足够,就递归左孩子 35 else Update(pos-sum[rt<<1],val,rson);//如果左孩子的空位数不够,那么就递归又孩子,但空位数要变成pos-sum[rt<<1] 36 PushUp(rt);//向上更新父节点的空位数 37 } 38 39 int main() 40 { 41 while(scanf("%d",&N)==1) 42 { 43 Build(1,N,1); 44 for (int i=1;i<=N;i++) scanf("%d%d",&p[i],&v[i]); 45 for (int i=N;i>=1;i--){ 46 Update(p[i]+1,v[i],1,N,1);//逆序遍历 47 } 48 for (int i=1;i<N;i++) printf("%d ",ans[i]); 49 printf("%d\n",ans[N]); 50 } 51 return 0; 52 }