HNOI2004 宠物收养所 解题报告
首先读完这题第一印象,是个裸题,很高兴。其次在打完代码之后,第二印象,很恶心,Treap的代码太长了,我今天下午敲了三遍,手都麻了。
废话不多说,正题。其实这个题不难,有几个点是很好的,首先,他的a值没有重复的,这就保证了你找前驱和后继的正确性,再次,没有宠物和人会同时在收养所内,那么你找的前驱和后继就不用判断是人还是动物。再次,就是AC了。
这个题一开始全WA,是因为没有注意前驱和后继不能为0的情况,导致自己领养自己或者自己被自己领养的情况出现,改了之后AC。
Treap的裸题,建议码一下。
直接上代码。
1 #include <cstdio> 2 #include <iostream> 3 #include <algorithm> 4 #include <cstring> 5 #include <cstdlib> 6 7 using namespace std; 8 const int maxn = 100000 + 5; 9 10 int N,flag,temp; 11 int Ans,size,root; 12 int Out = 0; 13 int ani_cnt = 0,er_cnt = 0; 14 int pre,bac; 15 16 struct data{ 17 int l,r,w,v,size,rnd; 18 }tr[maxn]; 19 void update(int k){ 20 tr[k].size = tr[tr[k].l].size + tr[tr[k].r].size + tr[k].w; 21 } 22 void rturn(int &k){ 23 int t = tr[k].l;tr[k].l = tr[t].r;tr[t].r = k; 24 tr[t].size = tr[k].size;update(k);k = t; 25 } 26 void lturn(int &k){ 27 int t = tr[k].r;tr[k].r = tr[t].l;tr[t].l = k; 28 tr[t].size = tr[k].size;update(k);k = t; 29 } 30 void insert(int &k,int x){ 31 if(k == 0){ 32 size ++;k = size; 33 tr[k].w = tr[k].size = 1; 34 tr[k].v = x;tr[k].rnd = rand(); 35 return; 36 } 37 tr[k].size ++; 38 if(tr[k].v == x){ 39 tr[k].w ++; 40 } 41 else if(x < tr[k].v){ 42 insert(tr[k].l,x); 43 if(tr[tr[k].l].rnd < tr[k].rnd) 44 rturn(k); 45 } 46 else { 47 insert(tr[k].r,x); 48 if(tr[tr[k].r].rnd < tr[k].rnd) 49 lturn(k); 50 } 51 } 52 void del(int &k,int x){ 53 if(k == 0) 54 return; 55 if(tr[k].v == x){ 56 if(tr[k].w > 1){ 57 tr[k].w --;tr[k].size --; 58 return; 59 } 60 if(tr[k].r*tr[k].l == 0) 61 k = tr[k].r + tr[k].l; 62 else if(tr[tr[k].l].rnd < tr[tr[k].r].rnd) 63 rturn(k),del(k,x); 64 else 65 lturn(k),del(k,x); 66 } 67 else if(x > tr[k].v) 68 tr[k].size --,del(tr[k].r,x); 69 else 70 tr[k].size --,del(tr[k].l,x); 71 } 72 int query_rank(int k,int x){ 73 if(k == 0) 74 return 0; 75 if(x == tr[k].v) 76 return tr[tr[k].l].size + 1; 77 else if(x > tr[k].v) 78 return tr[tr[k].l].size + tr[k].w + query_rank(tr[k].r,x); 79 else return query_rank(tr[k].l,x); 80 } 81 int query_num(int k,int x){ 82 if(k == 0) 83 return 0; 84 if(x <= tr[tr[k].l].size) 85 return query_num(tr[k].l,x); 86 else if(x > tr[tr[k].l].size + tr[k].w) 87 return query_num(tr[k].r,x-tr[tr[k].l].size-tr[k].w); 88 else return tr[k].v; 89 } 90 void query_pre(int k,int x){ 91 if(k == 0) 92 return; 93 if(x > tr[k].v){ 94 Ans = k;query_pre(tr[k].r,x); 95 } 96 else query_pre(tr[k].l,x); 97 } 98 void query_sub(int k,int x){ 99 if(k == 0) 100 return; 101 if(x < tr[k].v){ 102 Ans = k;query_sub(tr[k].l,x); 103 } 104 else query_sub(tr[k].r,x); 105 } 106 107 int main(){ 108 freopen("pet.in","r",stdin); 109 freopen("pet.out","w",stdout); 110 scanf("%d",&N); 111 for(int i = 1;i <= N;++ i){ 112 scanf("%d%d",&flag,&temp); 113 if(!flag){ 114 insert(root,temp); 115 ani_cnt ++; 116 if(er_cnt >= ani_cnt){//如果人多动物少,那么这个动物立刻被领养 117 query_pre(root,temp);pre = tr[Ans].v;Ans = 0; 118 query_sub(root,temp);bac = tr[Ans].v;Ans = 0; 119 if(pre == bac){ 120 Out += abs(pre-temp); 121 del(root,pre);del(root,temp); 122 } 123 else{ 124 if(temp-pre < bac-temp){ 125 if(pre){ 126 Out += temp-pre; 127 del(root,pre);del(root,temp); 128 } 129 else{ 130 Out += bac-temp; 131 del(root,bac);del(root,temp); 132 } 133 134 } 135 else{ 136 if(bac){ 137 Out += bac-temp; 138 del(root,bac);del(root,temp); 139 } 140 else{ 141 Out += temp-pre; 142 del(root,pre);del(root,temp); 143 } 144 } 145 } 146 --er_cnt;--ani_cnt; 147 } 148 } 149 else{ 150 insert(root,temp); 151 er_cnt ++; 152 if(ani_cnt >= er_cnt){//如果动物多人少,那么这个人立刻领养一个动物 153 query_pre(root,temp);pre = tr[Ans].v;Ans = 0; 154 query_sub(root,temp);bac = tr[Ans].v;Ans = 0; 155 if(pre == bac){ 156 Out += abs(pre-temp); 157 del(root,pre);del(root,temp); 158 } 159 else{ 160 if(temp-pre < bac-temp){ 161 if(pre){ 162 Out += temp-pre; 163 del(root,pre);del(root,temp); 164 } 165 else{ 166 Out += bac-temp; 167 del(root,bac);del(root,temp); 168 } 169 } 170 else{ 171 if(bac){ 172 Out += bac-temp; 173 del(root,bac);del(root,temp); 174 } 175 else{ 176 Out += temp-pre; 177 del(root,pre);del(root,temp); 178 } 179 } 180 } 181 --er_cnt;--ani_cnt; 182 } 183 } 184 Out %= 1000000; 185 } 186 printf("%d",Out%1000000); 187 fclose(stdin);fclose(stdout); 188 return 0; 189 }