• VIJOS P1647 不差钱 SBT


    【描述】

    同学们一起看了小品《不差钱》,LX神突发奇想,想刁难一下十八居士,他让十八居士模拟一下点菜的过程。

    【输入格式】

    输入第一行为一个数price,表示价钱大于price的菜赵本山都不要。

    以下几行表示点菜的过程,每行两个整数p,n

    p=1 表示在菜谱中添加一个价格为n的菜,这是第i个1号命令,这个菜的编号就是i,

    p=2 表示菜谱中第n号菜已卖完(但不代表菜谱中没有了这种菜),

    p=3 表示赵本山点第n贵的菜。

    输入文件以0结束。

    菜的价格0<n<=10^6。

    3种命令, 30%数据命令最多300次, 60%数据命令最多3000次, 100%数据命令最多100000次。

    【输出格式】

    对于每个p=3, 如果第n贵的菜价格高于price,则输出“Dui bu qi,Mei you.”。

    如果第n贵的菜价格不高于price,且没有卖完,则输出“You.”然后输出价格" m Yuan.";

    如果已卖完,则输出“Mei you. Zhe ge ke yi you. Zhe ge zhen mei you!”

    【分析】

    题目意思表达得比较明确,本题也很适合作为SBT的模板题。

    菜的编号就是存在SBT静态数组中的下标,只要加一个是否empty的标记即可。

    唯一稍微可能有点问题的是出现多个相同菜价的菜时的选择问题,一开始按照普通二叉树的写法写SBT的前趋后继,后来发现这样做其实是不严谨的,因为左右旋操作的存在,虽然一开始相等的数是插入到右边去,但是不能保证不会因为左旋而把父节点旋到左子树去了,所以最后只能保证左子树的值不大于根,右子树的值不小于根,相等值是完全没办法判断的。

    ......最后只好继续查找第n-1大、n-2大...第n+1大、第n+2大...直到找到不相等为止,O(k*logn)遍历一遍相等的数。

    好在测试时间上好像还不错,不知道又没有更好的办法?

      1 /* ***********************************************
      2 MYID    : Chen Fan
      3 LANG    : G++
      4 PROG    : VIJOS1647
      5 ************************************************ */
      6 
      7 #include <iostream>
      8 #include <cstdio>
      9 #include <cstring>
     10 #include <algorithm>
     11 
     12 using namespace std;
     13 
     14 #define MAXN 100010
     15 
     16 typedef struct sbtnod
     17 {
     18     int key,left,right,size;
     19     bool empty;
     20 } sbtnode;
     21 int sbttail,sbt;
     22 
     23 sbtnode tree[MAXN];
     24 
     25 void rrotate(int& t)
     26 {
     27     int k=tree[t].left;
     28     if (!k) return ;
     29     tree[t].left=tree[k].right;
     30     tree[k].right=t;
     31     tree[k].size=tree[t].size;
     32     tree[t].size=tree[tree[t].left].size+tree[tree[t].right].size+1;
     33     t=k;
     34 }
     35 
     36 void lrotate(int& t)
     37 {
     38     int k=tree[t].right;
     39     if (!k) return ;
     40     tree[t].right=tree[k].left;
     41     tree[k].left=t;
     42     tree[k].size=tree[t].size;
     43     tree[t].size=tree[tree[t].left].size+tree[tree[t].right].size+1;
     44     t=k;
     45 }
     46 
     47 void maintain(int& t,bool flag)
     48 {
     49     if (!t) return ;
     50     if (!flag)
     51         if (tree[tree[tree[t].left].left].size>tree[tree[t].right].size) rrotate(t);
     52         else if (tree[tree[tree[t].left].right].size>tree[tree[t].right].size) 
     53         {
     54             lrotate(tree[t].left);
     55             rrotate(t);
     56         } else return ;
     57     else
     58         if (tree[tree[tree[t].right].right].size>tree[tree[t].left].size) lrotate(t);
     59         else if (tree[tree[tree[t].right].left].size>tree[tree[t].left].size)
     60         {
     61             rrotate(tree[t].right);
     62             lrotate(t);
     63         } else return ;
     64     
     65     maintain(tree[t].left,false);
     66     maintain(tree[t].right,true);
     67     maintain(t,false);
     68     maintain(t,true);
     69 }
     70 
     71 void insert(int& t,int v)
     72 {
     73     if (!t)
     74     {
     75         sbttail++;
     76         tree[sbttail].key=v;
     77         tree[sbttail].size=1;
     78         tree[sbttail].empty=false;
     79         t=sbttail;
     80     } else 
     81     {
     82         tree[t].size++;
     83         if (v<tree[t].key) insert(tree[t].left,v);
     84         else insert(tree[t].right,v);
     85         maintain(t,v>=tree[t].key);
     86     }
     87 }
     88 
     89 int select(int t,int k)
     90 {
     91     if (k==tree[tree[t].left].size+1) return t;
     92     if (k<=tree[tree[t].left].size) return select(tree[t].left,k);
     93     else return select(tree[t].right,k-1-tree[tree[t].left].size);
     94 }
     95 
     96 int main()
     97 {
     98     freopen("1.txt","r",stdin);
     99     
    100     int pri;
    101     scanf("%d",&pri);
    102 
    103     sbt=0;
    104     sbttail=0;
    105 
    106     int p,n;
    107     while(scanf("%d%d",&p,&n)==2)
    108     {
    109         switch(p)
    110         {
    111             case 1:
    112                 insert(sbt,n);
    113                 break;
    114             case 2:
    115                 tree[n].empty=true;
    116                 break;
    117             case 3:
    118                 n=sbttail-n+1;
    119                 int temp=select(sbt,n);
    120                 if (tree[temp].key>pri) printf("Dui bu qi,Mei you.
    ");
    121                 else
    122                 {
    123                     bool done=false;
    124                     if (!tree[temp].empty) 
    125                     {
    126                         done=true;
    127                         printf("You. %d Yuan.
    ",tree[temp].key);
    128                     } else 
    129                     {
    130                         int pre,p=n;
    131                         while(p>1&&(!done))
    132                         {
    133                             p--;
    134                             pre=select(sbt,p);
    135                             if (tree[pre].key<tree[temp].key) break;
    136                             if (!tree[pre].empty)
    137                             {
    138                                 done=true;
    139                                 printf("You. %d Yuan.
    ",tree[temp].key);
    140                             }
    141                         }
    142                         int suc,s=n;
    143                         while(s<n&&(!done))
    144                         {
    145                             s++;
    146                             suc=select(sbt,s);
    147                             if (tree[suc].key>tree[temp].key) break;
    148                             if (!tree[suc].empty)
    149                             {
    150                                 done=true;
    151                                 printf("You. %d Yuan.
    ",tree[temp].key);
    152                             }
    153                         }
    154                     }
    155                     if (!done) printf("Mei you. Zhe ge ke yi you. Zhe ge zhen mei you!
    ");
    156                 }
    157         }
    158     }
    159 
    160     return 0;
    161 }
    View Code
  • 相关阅读:
    洛谷 P1231 教辅的组成
    BZOJ 2190: [SDOI2008]仪仗队
    Codeforces GYM 100741A . Queries
    COGS 1298. 通讯问题
    洛谷 P2604 [ZJOI2010]网络扩容
    codevs 1227 方格取数 2
    codevs 1004 四子连棋
    洛谷 P2319 [HNOI2006]超级英雄
    洛谷 P2153 [SDOI2009]晨跑
    插入排序
  • 原文地址:https://www.cnblogs.com/jcf94/p/4339927.html
Copyright © 2020-2023  润新知