• 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
    ",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
    ",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
    ",root);
    120     for (int i = cnt+1;i <= tot;i++)
    121     {
    122         printf("%d %d %d %d
    ",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
    ",k <= p[root].s?find(root,k)+delta:-1);
    141 //      debug();
    142     }
    143     printf("%d
    ",cnt);
    144     return 0;
    145 }
    View Code
  • 相关阅读:
    jquery、js调用iframe父窗口与子窗口元素的方法整理
    js中的各种宽高以及位置总结
    javascript call与apply关键字的作用
    javascript之window对象
    CSS3 3D立方体效果
    CSS3 3D transform变换
    JS查找字符串中出现次数最多的字符
    写一个函数将传入的字符串转换成驼峰表示法
    数组去重方法
    内核升级得一个模范
  • 原文地址:https://www.cnblogs.com/wulala979/p/3506157.html
Copyright © 2020-2023  润新知