不差钱 描述 同学们一起看了小品《不差钱》,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!”
输入样例
40 1 41 1 39 1 100 1 204 1 1 1 27 1 18 1 79 3 1 3 2 3 5 2 5 3 8 2 7 3 7 1 10 3 8 0
输出样例
Dui bu qi,Mei you. Dui bu qi,Mei you. You. 39 Yuan. Mei you. Zhe ge ke yi you. Zhe ge zhen mei you! Mei you. Zhe ge ke yi you. Zhe ge zhen mei you! You. 10 Yuan.
分析 题目意思表达得比较明确,本题也很适合作为SBT的模板题。
菜的编号就是存在SBT静态数组中的下标,只要加一个是否empty的标记即可。
唯一稍微可能有点问题的是出现多个相同菜价的菜时的选择问题,一开始按照普通二叉树的写法写SBT的前趋后继,后来发现这样做其实是不严谨的,因为左右旋操作的存在,虽然一开始相等的数是插入到右边去,但是不能保证不会因为左旋而把父节点旋到左子树去了,所以最后只能保证左子树的值不大于根,右子树的值不小于根,相等值是完全没办法判断的。
可能还是我的SBT写法不够严谨
……最后只好继续查找第n-1大、n-2大…第n+1大、第n+2大…直到找到不相等为止,O(k*logn)遍历一遍相等的数。
好在测试时间上好像还不错,不知道又没有更好的办法?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std;#define MAXN 100010 typedef struct sbtnod { int key,left,right,size; bool empty; } sbtnode; int sbttail,sbt;sbtnode tree[MAXN]; void rrotate (int & t) { int k=tree[t].left; if (!k) return ; tree[t].left=tree[k].right; tree[k].right=t; tree[k].size=tree[t].size; tree[t].size=tree[tree[t].left].size+tree[tree[t].right].size+1 ; t=k; } void lrotate (int & t) { int k=tree[t].right; if (!k) return ; tree[t].right=tree[k].left; tree[k].left=t; tree[k].size=tree[t].size; tree[t].size=tree[tree[t].left].size+tree[tree[t].right].size+1 ; t=k; } void maintain (int & t,bool flag) { if (!t) return ; if (!flag) if (tree[tree[tree[t].left].left].size>tree[tree[t].right].size) rrotate (t); else if (tree[tree[tree[t].left].right].size>tree[tree[t].right].size) { lrotate (tree[t].left); rrotate (t); } else return ; else if (tree[tree[tree[t].right].right].size>tree[tree[t].left].size) lrotate (t); else if (tree[tree[tree[t].right].left].size>tree[tree[t].left].size) { rrotate (tree[t].right); lrotate (t); } else return ; maintain (tree[t].left,false ); maintain (tree[t].right,true ); maintain (t,false ); maintain (t,true ); } void insert (int & t,int v) { if (!t) { sbttail++; tree[sbttail].key=v; tree[sbttail].size=1 ; tree[sbttail].empty=false ; t=sbttail; } else { tree[t].size++; if (v<tree[t].key) insert (tree[t].left,v); else insert (tree[t].right,v); maintain (t,v>=tree[t].key); } } int select (int t,int k) { if (k==tree[tree[t].left].size+1 ) return t; if (k<=tree[tree[t].left].size) return select (tree[t].left,k); else return select (tree[t].right,k-1 -tree[tree[t].left].size); } int main () { freopen ("1.txt" ,"r" ,stdin); int pri; scanf ("%d" ,&pri); sbt=0 ; sbttail=0 ; int p,n; while (scanf ("%d%d" ,&p,&n)==2 ) { switch (p) { case 1 : insert (sbt,n); break ; case 2 : tree[n].empty=true ; break ; case 3 : n=sbttail-n+1 ; int temp=select (sbt,n); if (tree[temp].key>pri) printf ("Dui bu qi,Mei you.\n" ); else { bool done=false ; if (!tree[temp].empty) { done=true ; printf ("You. %d Yuan.\n" ,tree[temp].key); } else { int pre,p=n; while (p>1 &&(!done)) { p--; pre=select (sbt,p); if (tree[pre].key<tree[temp].key) break ; if (!tree[pre].empty) { done=true ; printf ("You. %d Yuan.\n" ,tree[temp].key); } } int suc,s=n; while (s<n&&(!done)) { s++; suc=select (sbt,s); if (tree[suc].key>tree[temp].key) break ; if (!tree[suc].empty) { done=true ; printf ("You. %d Yuan.\n" ,tree[temp].key); } } } if (!done) printf ("Mei you. Zhe ge ke yi you. Zhe ge zhen mei you!\n" ); } } } return 0 ; }