bzoj 1503: [NOI 2004]郁闷的出纳员

这道题整整搞了我5天。。。。用到了数列的插入,删除和查询第K大

写的第一道平衡树题。。可以用各种平衡树和线段树来写,不失为一道极佳的平衡树练手题(据说树状数组也可以??Orz)

一开始是用splay,splay网上的code大部分都用了指针我根本看不懂。

后来找葱娘的ACcode用数组写的才总算看懂一点。。我理解了一晚上,写了一上午,调了一下午加晚上。。

葱娘的代码就是神,一开始我还以为要用到区间修改,后面发现葱娘用一个变量记录增量就可以了(Orz!!)

附上单旋SPLAYcode,这道题数据比较水,双旋单旋差不多

  1 /*
  2 ID:WULALA
  3 PROB:splay bzoj1503
  4 LANG:C++
  5 */
  6 #include <cstdio>
  7 #include <cstring>
  8 #include <algorithm>
  9 #include <cmath>
 10 #include <iostream>
 11 #include <ctime>
 12 #include <set>
 13 #define N 100008
 14 #define M
 15 #define mod
 16 #define mid(l,r) ((l+r) >> 1)
 17 #define INF 0x7ffffff
 18 using namespace std;
 19   
 20 struct node
 21 {
 22      int l,r,f,key,s,v;
 23 }tree[N];
 24   
 25 int n,m,root,delta,l,tot = 1;
 26   
 27 inline void update(int x)
 28 {
 29     tree[x].s = tree[tree[x].l].s + tree[tree[x].r].s + 1;
 30 }
 31   
 32 inline void zig(int &x)
 33 {
 34     int y = tree[x].f;
 35     int z = tree[y].f;
 36     if (y == tree[z].l) tree[z].l = x;
 37     else tree[z].r = x;
 38     tree[x].f = z;
 39     tree[y].l = tree[x].r;
 40     tree[tree[x].r].f = y;
 41     tree[x].r = y;
 42     tree[y].f = x;
 43     update(y); update(x);
 44     if (y == root) root = x;
 45 }
 46   
 47 inline void zag(int &x)
 48 {
 49     int y = tree[x].f;
 50     int z = tree[y].f;
 51     if (y == tree[z].l) tree[z].l = x;
 52     else tree[z].r = x;
 53     tree[x].f = z;
 54     tree[y].r = tree[x].l;
 55     tree[tree[x].l].f = y;
 56     tree[y].f = x;
 57     tree[x].l = y;
 58     update(y); update(x);
 59     if (y == root) root = x;  
 60 }
 61   
 62 void splay(int &x,int d)
 63 {
 64     while (tree[x].f != d)
 65     {
 66         if (tree[tree[x].f].l == x) zig(x);
 67         else zag(x);
 68     }
 69 }
 70   
 71 void insert(int k)
 72 {
 73     if (!root)
 74     {
 75         root = ++tot;
 76         tree[tot].key = k;
 77         tree[tot].s = 1;
 78         return;
 79     }
 80     int p = root,z;
 81     while(p)
 82     {
 83         z = p;
 84         ++tree[p].s;
 85         if (k < tree[p].key) p = tree[p].l;
 86         else p = tree[p].r;
 87     }
 88     if (tree[z].key>k) tree[z].l = ++tot;
 89     else tree[z].r = ++tot;
 90     tree[tot].key = k;
 91     tree[tot].s = 1;
 92     tree[tot].f = z;
 93     splay(tot,0);
 94 }
 95   
 96 int find(int x,int k)
 97 {
 98     if (k <= tree[tree[x].r].s)
 99         return (find(tree[x].r,k));
100     if (k == tree[tree[x].r].s+1)
101         return tree[x].key;
102     return find(tree[x].l,k-tree[tree[x].r].s-1); 
103 }
104   
105 int dec(int &x,int f) 
106 {
107     if (!x) return 0;
108     int k;
109     if (tree[x].key + delta < m)
110     {
111         k = dec(tree[x].r,x) + tree[tree[x].l].s + 1;
112         tree[tree[x].r].s = tree[x].s-k;
113         x = tree[x].r;
114         tree[x].f = f;
115     }
116     else
117     {
118         k = dec(tree[x].l,x);
119         tree[x].s -= k;
120     }
121     return k;
122 }
123   
124 int main()
125 {
126 //  freopen("input.txt","r",stdin);
127 //  freopen("output.txt","w",stdout);
128     scanf("%d%d",&n,&m);
129     while(n--)
130     {
131         char c[1];
132         int k;
133         scanf("%s%d",&c,&k);
134         if (c[0] == 'I' && k >= m) insert(k - delta);
135         else if (c[0] == 'F')
136             printf("%d\n",k <= tree[root].s?find(root,k)+delta:-1);
137         else if (c[0] == 'A')
138             delta += k;
139         else if (c[0] == 'S')
140             {delta -= k; l+=dec(root,0);}
141     }
142     printf("%d\n",l);
143     return 0;
144 }
View Code

看了一下HZW的treap在较好情况下比我的快了3倍。。人家还会用线段树做。。好自卑。。我连随机函数都不会用(orz!!)

然后又用sbt写,sbt也是刚学,各种变参不会用,又调试了一下午加晚上,终于还是写出来了

葱娘说SBT是傻逼树(SBTree),我特么觉得是超变态(SuperBT),唉。。这就是神犇与蒟蒻的差距啊。。

喜闻乐见的贴代码

  1 /*
  2 ID:WULALA
  3 PROB:SBT bzoj1503
  4 LANG:C++
  5 */
  6 #include <cstdio>
  7 #include <cstring>
  8 #include <algorithm>
  9 #include <cmath>
 10 #include <iostream>
 11 #include <ctime>
 12 #include <set>
 13 #define N 100008
 14 #define M
 15 #define mod
 16 #define mid(l,r) ((l+r) >> 1)
 17 #define INF 0x7ffffff
 18 using namespace std;
 19   
 20 int n,MIN,delta,cnt,tot,root;
 21   
 22 struct WULALA
 23 {
 24     int l,r,s,v;
 25 }p[N];
 26   
 27 void zig(int &x)
 28 {
 29     int y = p[x].l;
 30     p[x].l = p[y].r;
 31     p[y].r = x;
 32     p[y].s = p[x].s;
 33     p[x].s = p[p[x].l].s + p[p[x].r].s + 1;
 34     x = y;
 35 }
 36   
 37 void zag(int &x)
 38 {
 39     int y = p[x].r;
 40     p[x].r = p[y].l;
 41     p[y].l = x;
 42     p[y].s = p[x].s;
 43     p[x].s = p[p[x].l].s + p[p[x].r].s + 1;
 44     x = y;
 45 }
 46   
 47 void maintain(int &x,bool flag)
 48 {
 49     int l = p[x].l,r = p[x].r;
 50     if (!flag)
 51     {
 52         if (p[p[l].l].s > p[r].s)
 53             zig(x);
 54         else if (p[p[l].r].s > p[r].s)
 55 //          zag(l),zig(x);   
 56             zag(p[x].l),zig(x);//x已改变,下同理;
 57         else return ;
 58     }
 59     else
 60     {
 61         if (p[p[r].r].s > p[l].s)
 62             zag(x);
 63         else if (p[p[r].l].s > p[l].s)
 64             zig(p[x].r),zag(x);
 65         else return ;
 66     }
 67 //  maintain(l,false);
 68 //  maintain(r,true);
 69     maintain(p[x].l,false);
 70     maintain(p[x].r,true);//x已改变
 71     maintain(x,false);
 72     maintain(x,true);
 73 }
 74   
 75 void insert(int &x,int k)
 76 {
 77     if (!x)
 78     {
 79         x = ++tot;
 80         p[x].s = 1;
 81         p[x].v = k;
 82     }
 83     else
 84     {
 85         p[x].s++;//!!
 86         if (p[x].v > k) insert(p[x].l,k);
 87         else insert(p[x].r,k);
 88         maintain(x,k >= p[x].v);
 89     }
 90 }
 91   
 92 int del(int &x)
 93 {
 94     int ans;
 95     if (!x) return 0;
 96     if (p[x].v + delta < MIN)
 97     {
 98         ans = p[p[x].l].s + 1 + del(p[x].r);
 99         p[p[x].r].s = p[x].s - ans;
100         x = p[x].r;
101     }
102     else
103     {
104         ans = del(p[x].l);
105         p[x].s -= ans;
106     }
107     return ans;
108 }
109   
110 int find(int x,int k)
111 {
112     if (p[p[x].r].s >= k) return find(p[x].r,k);
113     else if (p[p[x].r].s == k - 1) return p[x].v;
114     else return find(p[x].l,k - p[p[x].r].s - 1);
115 }
116   
117 void debug()
118 {
119     printf("%d\n",root);
120     for (int i = cnt+1;i <= tot;i++)
121     {
122         printf("%d %d %d %d\n",p[i].l,p[i].r,p[i].s,p[i].v);
123     }
124 }
125   
126 int main()
127 {
128     scanf("%d%d",&n,&MIN);
129     while (n--)
130     {
131         char c[1]; int k;
132         scanf("%s%d",c,&k);
133         if (c[0] == 'I' && k >= MIN)
134             insert(root,k-delta);
135         else if (c[0] == 'A')
136             delta += k;
137         else if (c[0] == 'S')
138             delta -= k,cnt += del(root);
139         else if (c[0] == 'F')
140             printf("%d\n",k <= p[root].s?find(root,k)+delta:-1);
141 //      debug();
142     }
143     printf("%d\n",cnt);
144     return 0;
145 }
View Code

 

posted @ 2014-01-05 19:15  乌拉拉979  阅读(172)  评论(0编辑  收藏  举报