poj 2828【线段树 单点更新】

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 }
poj 2828

 

posted @ 2017-08-05 16:29  ╰追憶似水年華ぃ╮  阅读(123)  评论(0编辑  收藏  举报