HDU 4441 Queue Sequence

http://acm.hdu.edu.cn/showproblem.php?pid=4441

题意:对于一个序列,每次有三种操作
   insert pos  表示在pos插入一个数,这个数是最小的正数没有在序列中出现的。而且还要在某个位置插入他的相反数,使得这个序列满足队列的出入顺序(正表示进,负表示出)
   remove num 表示在序列中把num以及-num两数去掉
   query num 把num与-num之间的数求和输出

     这题我本来实在是没有思路,看起来像维护一个线段树,这样求和好办,但是序列的长度是会变的,而且元素的绝对位置是会变的,线段树就无法解决了。

     通过这题我才了解了一个新的数据结构:Splay Tree。每个节点不仅要保存元素值,还需要维护以当前节点为根的子树所含的正数个数和负数个数以及从开头到当前元素的序列和。在一棵二叉查找树种如何在第i个元素之前插入一个元素呢?我原先想构造二叉树使得后序遍历为当前序列,这样要在一个元素前插入一个节点,就在以这个节点的左子树的最右端插入就可以了,这样不怕没位置。但问题是,为了提高查找树的效率,无论用AVL Tree 还是 Splay Tree 都要用旋转操作,这一旋转就会破坏这个关系。要是旋转操作保持树的原有性质,就只能用中序:节点的左子树的所有元素都在当前元素的左边,节点的右子树的所有元素都在当前元素的右边。那如何在指定位置插入呢,那只能先断开节点和一个子树的联系,在此之间插入新元素节点再连接起来。

     用Splay Tree的好处是SP树可以把一个节点提到树根并保持整棵树的性质,这样在插入、删除以及合并时更加方便,这样可以很快地把树以一个标准分为两个部分,更据偏序关系来操作。由于Splay Tree需要多次旋转,插入删除时也会更改树的结构,所以要注意节点的更新和更新的顺序!

     确定当前不在序列中的最小正整数用线段树来维护就好了。这题用了两种数据结构和变异的算法,逻辑复杂,再用类封装,所以代码量比较大,我也调试了许久,问题出来节点更新和些小细节上,不过总算AC了。

  1 #include <stdio.h>
  2 #include <string.h>
  3 #include <stdlib.h>
  4 inline int mymin(int a,int b)
  5 {
  6     if (a==-1) return b;
  7     if (b==-1) return a;
  8     return a>b?b:a;
  9 }
 10 struct segtree
 11 {
 12 #define sbegin 1,100000,1
 13     int tree[100001<<2];
 14     segtree(){build(sbegin);}
 15     void build(int l,int r,int rt)
 16     {
 17         if (l==r){tree[rt]=l;return;}
 18         int mid=(l+r)>>1;
 19         build(l,mid,rt<<1);
 20         build(mid+1,r,rt<<1|1);
 21         tree[rt]=mymin(tree[rt<<1],tree[rt<<1|1]);
 22     }
 23     void update(int l,int r,int rt,int p,int op)
 24     {
 25         if (l==r && l==p){tree[rt]=op; return;}
 26         int mid=(l+r)>>1;
 27         if (p<=mid) update(l,mid,rt<<1,p,op);
 28         if (p>mid) update(mid+1,r,rt<<1|1,p,op);
 29         tree[rt]=mymin(tree[rt<<1],tree[rt<<1|1]);
 30     }
 31     int query(){return tree[1]; }
 32     void insert(int p) { update(sbegin,p,-1);}
 33     void del(int p){update(sbegin,p,p); }
 34 }*myseg;
 35 struct spt
 36 {
 37 
 38     spt(){root=NULL;}
 39     struct node
 40     {
 41         int data;
 42         long long sum;
 43         int zs,fs;
 44         node *left,*right,*father;
 45         node(int d=0,node* a=NULL,node *b=NULL,node *c=NULL):data(d),left(a),right(b),father(c)
 46         {sum=data;zs=data>0;fs=data<0;}
 47     }*root;
 48     void print(node *p)
 49     {
 50         if (p==NULL) return;
 51         print(p->left);
 52         printf("[%d] data: %d sum: %I64d zs: %d fs:%d | %4d %4d %4d\n",p,p->data,p->sum,p->zs,p->fs,p->father,p->left,p->right);
 53         print(p->right);
 54     }
 55     void update(node *k)
 56     {
 57         k->sum=k->data;
 58         if (k->left) k->sum+=k->left->sum;
 59         if (k->right) k->sum+=k->right->sum;
 60         k->zs=k->data>0;
 61         if (k->left) k->zs+=k->left->zs;
 62         if (k->right) k->zs+=k->right->zs;
 63         k->fs=k->data<0;
 64         if (k->left) k->fs+=k->left->fs;
 65         if (k->right) k->fs+=k->right->fs;
 66     }
 67     void zig(node *k)
 68     {
 69         node* fa=k->father;
 70         fa->left=k->right;
 71         if (k->right) k->right->father=fa;
 72         k->right=fa;
 73         k->father=fa->father;
 74         fa->father=k;
 75         update(fa);
 76         update(k);
 77         if (!k->father) return;
 78         if (k->father->left==fa)
 79             k->father->left=k;
 80         else
 81             k->father->right=k;
 82         update(k->father);
 83     }
 84     void zag(node *k)
 85     {
 86         node* fa=k->father;
 87         fa->right=k->left;
 88         if (k->left) k->left->father=fa;
 89         k->left=fa;
 90         k->father=fa->father;
 91         fa->father=k;
 92         update(fa);
 93         update(k);
 94         if (!k->father) return;
 95         if (k->father->left==fa)
 96             k->father->left=k;
 97         else
 98             k->father->right=k;
 99         update(k->father);
100     }
101     void splay(node *k,node *&root)
102     {
103         while (k->father)
104         {
105             node *fa=k->father;
106             if (fa->father==NULL)
107             {
108                 if (k==fa->left) zig(k);
109                 else zag(k);
110             }
111             else
112             {
113                 node *gf=fa->father;
114                 if (fa==gf->left && k==fa->left)
115                 {
116                     zig(fa);
117                     zig(k);
118                 }
119                 if (fa==gf->left && k==fa->right)
120                 {
121                     zag(k);
122                     zig(k);
123                 }
124                 if (fa==gf->right && k==fa->left)
125                 {
126                     zig(k);
127                     zag(k);
128                 }
129                 if (fa==gf->right && k==fa->right)
130                 {
131                     zag(fa);
132                     zag(k);
133                 }
134             }
135         }
136         root=k;
137     }
138     node *findmax(node *&p)
139     {
140         node *t=p;
141         while (t->right) t=t->right;
142         splay(t,p);
143         return t;
144     }
145     node* insert(int data,int tp)
146     {
147         if (root==NULL) {root=new node(data); return root;}
148         if (root->zs+root->fs<tp)
149         {
150             findmax(root);
151             root->right=new node(data);
152             root->right->father=root;
153             update(root);
154             return root->right;
155         }
156         find(tp);
157         node *t=root->left;
158         root->left=new node(data);
159         root->left->father=root;
160         root->left->left=t;
161         if (t) t->father=root->left;
162         update(root->left);
163         update(root);
164         return root->left;
165     }
166     node* insert2(int data,int tp)
167     {
168          if (root->fs<tp)
169         {
170             findmax(root);
171             root->right=new node(data);
172             root->right->father=root;
173             update(root);
174             return root->right;
175         }
176         node *q=__find2(tp,root);
177         if (q) splay(q,root);
178         node *t=root->left;
179         root->left=new node(data);
180         root->left->father=root;
181         root->left->left=t;
182         if (t) t->father=root->left;
183         update(root->left);
184         update(root);
185         return root->left;
186     }
187     node* __find(int tp,node *root)
188     {
189         if (root==NULL) return NULL;
190         int tem=0;
191         if (root->left) tem=root->left->zs+root->left->fs;
192         if (root->left && tp<=tem ) return __find(tp,root->left);
193         if (tem+1==tp) return root;
194         return __find(tp-tem-1,root->right);
195     }
196     node* __find2(int tp,node *root)
197     {
198         if (root==NULL) return NULL;
199         int tem=0;
200         if (root->left) tem=root->left->fs;
201         if (root->left && tp<=tem ) return __find2(tp,root->left);
202         if (tem+(root->data<0)==tp) return root;
203         return __find2(tp-tem-(root->data<0),root->right);
204     }
205     node* find(int tp)
206     {
207         node *q=__find(tp,root);
208         if (q) splay(q,root);
209         return q;
210     }
211     node* join(node *a,node *b)
212     {
213         if (a)a->father=NULL;
214         if (b) b->father=NULL;
215        if (!a || !b) return (node *)((int)a|(int)b);
216         node *t=findmax(a);
217         t->right=b;
218         b->father=t;
219         update(t);
220         return t;
221     }
222     void remove(node *q)
223     {
224          splay(q,root);
225         node *tem=root;
226         root=join(root->left,root->right);
227         delete tem;
228     }
229     void del(node *p)
230     {
231         if (p==NULL) return;
232         del(p->left);
233         del(p->right);
234         delete p;
235     }
236     ~spt(){del(root);}
237 }*mysp;
238 struct pair
239 {
240     spt::node *first,*second;
241     pair(spt::node *a=NULL,spt::node *b=NULL):first(a),second(b){}
242 }path[100002];
243 void work(char type,int n)
244 {
245     if (type=='i')
246     {
247         int data=myseg->query();
248         myseg->insert(data);
249         spt::node *a=mysp->insert(data,n+1);
250         mysp->splay(a,mysp->root);
251         int zs=0;
252         if (a->left) zs+=a->left->zs;
253         spt::node *b=mysp->insert2(-data,zs+1);
254         path[data]=pair(a,b);
255     }
256     if (type=='r')
257     {
258         pair t=path[n];
259         mysp->remove(t.first);
260         mysp->remove(t.second);
261         myseg->del(n);
262     }
263     if (type=='q')
264     {
265         long long ans=0;
266         pair t=path[n];
267         mysp->splay(t.second,mysp->root);
268         if (mysp->root->left) ans+=mysp->root->left->sum;
269         mysp->splay(t.first,mysp->root);
270         ans-=mysp->root->data;
271         if (mysp->root->left) ans-=mysp->root->left->sum;
272         printf("%I64d\n",ans);
273     }
274 }
275 int main()
276 {
277    int n,cas=0;
278    while (~scanf("%d",&n))
279    {
280        printf("Case #%d:\n",++cas);
281        mysp=new spt;
282        myseg=new segtree;
283        char cmd[256];
284        int t;
285        while (n--)
286        {
287            scanf("%s%d",cmd,&t);
288            work(cmd[0],t);
289        }
290        delete mysp;
291        delete myseg;
292    }
293 }
代码

 

posted @ 2013-08-14 23:45  wuminye  阅读(432)  评论(0编辑  收藏  举报