您的位置:首页 > 其它

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

2014-10-24 20:14 369 查看
这题时间限制的紧(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;		// mileage
struct mem *le, *ri, *pa;	// left, right, parent
bool 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 DEBUG
freopen("in.txt", "r", stdin);
#endif
rbtree = 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 DEBUG
printf("debug: %s %ld\n", tid, tma);
#endif
if(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 DEBUG
printf("%s: ", pm->id);
#endif
printf("%ld\n", pm->ma);
}
else
printf("No Info\n");
}
return 0;
}

bool search(char *id, Mem **ppm)
{
*ppm = rbtree;
#ifdef DEBUG
printf("\nsearch: %s\n", id);
#endif
while(*ppm != pNIL){
#ifdef DEBUG
printf("%s %ld\n", (*ppm)->id, (*ppm)->ma);
#endif
int 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;
else
px = 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;
else
py->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;
else
z->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;
else
z->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 table

long hash(char *id);
void insert(char *id, long ma);		// mileage

int main(void)
{
#ifdef DEBUG
freopen("in.txt", "r", stdin);
#endif
memset(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 DEBUG
printf("\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;
}
else
pm = 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;
}
else
pm = pm->next;
}
if((pm = (Mem*)malloc(sizeof(Mem))) == NULL)
exit(1);
strcpy(pm->id, id);
pm->ma = ma;
if(pre != NULL)
pre->next = pm;
else
ht[h] = pm;
}
</span>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  PAT