noi2004 郁闷的出纳员
用SBT神树做的,开始select居然打错了,maintain里就、自己没分清左右,树转烂了,无语。
外边有一个工资总标记量就行了。
View Code
1 program cashier(input,output); 2 const 3 oo = 9999999; 4 var 5 left,right,keys,s : array[0..200000] of longint; 6 money : longint; 7 n,tot,root : longint; 8 answer : longint; 9 minmoney : longint; 10 procedure left_rotate(var t: longint ); 11 var 12 k : longint; 13 begin 14 k:=right[t]; 15 right[t]:=left[k]; 16 left[k]:=t; 17 s[k]:=s[t]; 18 s[t]:=s[left[t]]+s[right[t]]+1; 19 t:=k; 20 end; { left_rotate } 21 procedure right_rotate(var t :longint ); 22 var 23 k : longint; 24 begin 25 k:=left[t]; 26 left[t]:=right[k]; 27 right[k]:=t; 28 s[k]:=s[t]; 29 s[t]:=s[left[t]]+s[right[t]]+1; 30 t:=k; 31 end; { right_rotate } 32 procedure maintain(var t : longint;flag:boolean ); 33 begin 34 if not flag then 35 begin 36 if s[left[left[t]]]>s[right[t]] then 37 right_rotate(t) 38 else 39 if s[right[left[t]]]>s[right[t]] then 40 begin 41 left_rotate(left[t]); //错误点 42 right_rotate(t); 43 end 44 else 45 exit; 46 end 47 else 48 if s[right[right[t]]]>s[left[t]] then 49 left_rotate(t) 50 else 51 if s[left[right[t]]]>s[left[t]] then 52 begin 53 right_rotate(right[t]); 54 left_rotate(t); 55 end 56 else 57 exit; 58 maintain(left[t],false); 59 maintain(right[t],true); 60 maintain(t,false); 61 maintain(t,true); 62 end; { maintain } 63 procedure insect(var now : longint; k:longint ); 64 begin 65 if now=0 then 66 begin 67 inc(tot); 68 now:=tot; 69 left[now]:=0; 70 right[now]:=0; 71 s[now]:=1; 72 keys[now]:=k; 73 end 74 else 75 begin 76 inc(s[now]); 77 if k>=keys[now] then 78 insect(right[now],k) 79 else 80 insect(left[now],k); 81 maintain(now,k>=keys[now]); 82 end; 83 end; { insect } 84 function select(now,k :longint ):longint; 85 begin 86 if k=s[left[now]]+1 then 87 exit(keys[now]); 88 if k<=s[left[now]] then //错误点 89 select:=select(left[now],k) 90 else 91 select:=select(right[now],k-s[left[now]]-1); 92 end; { select } 93 function delete(var now : longint;k:longint ):longint; 94 begin 95 dec(s[now]); 96 if (k=keys[now])or((k<keys[now])and(left[now]=0))or((k>=keys[now])and(right[now]=0)) then 97 begin 98 delete:=keys[now]; 99 if (left[now]=0)or(right[now]=0) then 100 now:=left[now]+right[now] 101 else 102 keys[now]:=delete(left[now],keys[now]+1); 103 end 104 else 105 if k<keys[now] then 106 delete:=delete(left[now],k) 107 else 108 delete:=delete(right[now],k); 109 end; { delete } 110 function getmin(now :longint ):longint; 111 begin 112 if now=0 then 113 exit(oo); 114 getmin:=getmin(left[now]); 115 if getmin=oo then 116 exit(keys[now]); 117 end; { getmin } 118 procedure main; 119 var 120 i,x : longint; 121 ch : char; 122 tmp : longint; 123 begin 124 root:=0; 125 tot:=0; 126 fillchar(left,sizeof(left),0); 127 fillchar(right,sizeof(right),0); 128 fillchar(keys,sizeof(keys),0); 129 fillchar(s,sizeof(s),0); 130 answer:=0; 131 money:=0; 132 readln(n,minmoney); 133 for i:=1 to n do 134 begin 135 read(ch); 136 case ch of 137 'I' : begin 138 readln(x); 139 if x<minmoney then 140 continue 141 else 142 insect(root,x-money); 143 end; 144 'A' : begin 145 readln(x); 146 money:=money+x; 147 end; 148 'S' : begin 149 readln(x); 150 dec(money,x); 151 tmp:=getmin(root); 152 while (tmp+money<minmoney)and(s[root]>0) do 153 begin 154 inc(answer); 155 delete(root,tmp); 156 tmp:=getmin(root); 157 end; 158 end; 159 'F' : begin 160 readln(x); 161 if x>s[root] then 162 writeln(-1) 163 else 164 writeln(select(root,s[root]-x+1)+money); 165 end; 166 end; { case } 167 end; 168 writeln(answer); 169 end; { main } 170 begin 171 assign(input,'cashier.in');reset(input); 172 assign(output,'cashier.out');rewrite(output); 173 main; 174 close(input); 175 close(output); 176 end.