PAT DS 506 航空公司VIP客户查询

来源:互联网 发布:angrybots 源码下载 编辑:程序博客网 时间:2024/04/30 20:33

这题时间限制的紧(150ms),导致第一种红黑树的办法最后一个case超时(第二个case用了149ms,汗。。。)。

红黑树的办法就是逐个添加到树里,在ins_update函数里调整,使之符合红黑树规则。具体参见《算法导论》。代码参看附录A。

想到过会不会是strcmp比较费时间,可是简单测试过之后发现,长度为18的字符串之间的strcmp并不比整型数的比较慢多少。见下图(图中数值均为clock_t):


代码参看附录B。

幸好,最后想到应该用hash表来做。便写个简易的hash函数,将身份证号按3,3,4,4,4个数相加,再对10求余,正好10的5次方数量级。代码见附录C。


后记:

粗略算一下的话,红黑树时间复杂度为nlogn数量级,我这个程序大约是n(10+10logn),10^5数据量的话便大约是10^7。加上一条语句大约几个指令,一条指令需要几个到几十个时钟周期,最后便大约是10^8数量级的时钟周期。150ms大约也是10^8时钟周期。CPU是3GHz的话,需要333ms才比较保险,所以是危险的。


附录A:

<span style="font-size:18px;">#include <stdio.h>#include <assert.h>#include <stdbool.h>#include <string.h>#include <malloc.h>#include <stdlib.h>int n, k, m;typedef struct mem{char id[19];long ma;// mileagestruct mem *le, *ri, *pa;// left, right, parentbool color;// true if red, false if black}Mem;Mem NIL = {"", 0, NULL, NULL, NULL, false};Mem *rbtree, *pNIL = &NIL;// red-black tree, ..void insert(char *id, long ma);bool search(char *id, Mem **ppm);int main(void){#ifdef DEBUGfreopen("in.txt", "r", stdin);#endifrbtree = pNIL;scanf("%d%d", &n, &k);int i=0;Mem *pm;for(; i<n; ++i){char tid[19];long tma;scanf("%s%ld", tid, &tma);#ifdef DEBUGprintf("debug: %s %ld\n", tid, tma);#endifif(tma < k)tma = k;insert(tid, tma);}scanf("%d", &m);for(i=0; i<m; ++i){char tid[19];scanf("%s", tid);if(search(tid, &pm)){assert(pm != pNIL && pm != NULL);#ifdef DEBUGprintf("%s: ", pm->id);#endifprintf("%ld\n", pm->ma);}elseprintf("No Info\n");}return 0;}bool search(char *id, Mem **ppm){*ppm = rbtree;#ifdef DEBUGprintf("\nsearch: %s\n", id);#endifwhile(*ppm != pNIL){#ifdef DEBUGprintf("%s %ld\n", (*ppm)->id, (*ppm)->ma);#endifint sc = strcmp(id, (*ppm)->id);if(sc == 0)return true;else if(sc < 0)*ppm = (*ppm)->le;else*ppm = (*ppm)->ri;}return false;}void left_rotate(Mem *pm);void right_rotate(Mem *pm);void ins_update(Mem *pm);void insert(char *id, long ma){Mem *px = rbtree, *py = pNIL;int sc;while(px != pNIL){py = px;sc = strcmp(id, px->id);if(sc == 0){px->ma += ma;return;}else if(sc < 0)px = px->le;elsepx = px->ri;}Mem *pm = (Mem*)malloc(sizeof(Mem));if(pm == NULL)exit(1);strcpy(pm->id, id);pm->ma = ma;pm->le = pm->ri = pNIL;pm->pa = py;pm->color = true;if(py == pNIL)rbtree = pm;else if(sc < 0)py->le = pm;elsepy->ri = pm;ins_update(pm);}void ins_update(Mem *z){Mem *y;while(z->pa->color){if(z->pa == z->pa->pa->le){y = z->pa->pa->ri;if(y->color){z->pa->color = false;y->color = false;z->pa->pa->color = true;z = z->pa->pa;}else{if(z == z->pa->ri){z = z->pa;left_rotate(z);}z->pa->color = false;z->pa->pa->color = true;right_rotate(z->pa->pa);}}else{y = z->pa->pa->le;if(y->color){z->pa->color = false;y->color = false;z->pa->pa->color = true;z = z->pa->pa;}else{if(z == z->pa->le){z = z->pa;right_rotate(z);}z->pa->color = false;z->pa->pa->color = true;left_rotate(z->pa->pa);}}}rbtree->color = false;}void left_rotate(Mem *z){assert(z != pNIL && z->ri != pNIL);Mem *y = z->ri;z->ri = y->le;if(y->le != pNIL)y->le->pa = z;y->pa = z->pa;if(z->pa == pNIL)rbtree = y;else if(z == z->pa->le)z->pa->le = y;elsez->pa->ri = y;y->le = z;z->pa = y;}void right_rotate(Mem *z){assert(z != pNIL && z->le != pNIL);Mem *y = z->le;z->le = y->ri;if(y->ri != pNIL)y->ri->pa = z;y->pa = z->pa;if(z->pa == pNIL)rbtree = y;else if(z == z->pa->ri)z->pa->ri = y;elsez->pa->le = y;y->ri = z;z->pa = y;}</span>

附录B:

<span style="font-size:18px;">#include <stdio.h>#include <string.h>#include <time.h>char id[10000000][19];int main(void){clock_t start, finish;long i=0, j;for(i=0; i<10000000; ++i)sprintf(id[i], "%18ld", i);start = clock();for(i=1; i<10000000; ++i)j = strcmp(id[i], id[i-1]);finish = clock();printf("strcmp: %ld %ld %ld\n", start, finish, (finish-start));start = clock();for(i=1; i<10000000; ++i){j = id[i][0] > id[i-1][0];j = id[i][1] > id[i-1][1];}finish = clock();printf("long: %ld %ld %ld\n", start, finish, (finish-start));return 0;}</span>


附录C:

<span style="font-size:18px;">#include <stdio.h>#include <string.h>#include <malloc.h>#include <stdlib.h>int n, k, m;typedef struct s_mem{char id[19];long ma;struct s_mem *next;}Mem;Mem *ht[100000];// hash tablelong hash(char *id);void insert(char *id, long ma);// mileageint main(void){#ifdef DEBUGfreopen("in.txt", "r", stdin);#endifmemset(ht, 0, sizeof(ht));scanf("%d%d", &n, &k);int i=0;for(i=0; i<n; ++i){char tid[19];long tma;scanf("%s%ld", tid, &tma);if(tma < k)tma = k;insert(tid, tma);#ifdef DEBUGprintf("\ninsert %s & hash table:\n", tid);long j=0;for(; j<100000; ++j){Mem *dpm = ht[j];while(dpm != NULL){printf("%ld: %s %ld\n", j, dpm->id, dpm->ma);dpm = dpm->next;}}#endif}scanf("%d", &m);for(i=0; i<m; ++i){char tid[19];scanf("%s", tid);long h = hash(tid);Mem *pm = ht[h];while(pm != NULL){if(strcmp(tid, pm->id)==0){printf("%ld\n", pm->ma);break;}elsepm = pm->next;}if(pm == NULL)printf("No Info\n");}return 0;}long hash(char *id){long h = (id[0]+id[1]+id[2])%10*10000;h += (id[3]+id[4]+id[5])%10*1000;h += (id[6]+id[7]+id[8]+id[9])%10*100;h += (id[10]+id[11]+id[12]+id[13])%10*10;h += (id[14]+id[15]+id[16]+id[17])%10;return h;}void insert(char *id, long ma){long h = hash(id);Mem *pm = ht[h], *pre=ht[h];while(pm != NULL){pre = pm;if(strcmp(id, pm->id) == 0){pm->ma += ma;return;}elsepm = pm->next;}if((pm = (Mem*)malloc(sizeof(Mem))) == NULL)exit(1);strcpy(pm->id, id);pm->ma = ma;if(pre != NULL)pre->next = pm;elseht[h] = pm;}</span>


0 0
原创粉丝点击