Untitled
unknown
plain_text
2 years ago
5.4 kB
3
Indexable
#define MAX_S 20002 #define MAX_SCORE 300000 #define BLOCK_SIZE 200 #define NUM_BLOCK 1501 #define getHashIdx(id) id % MAX_S #define getScoreIdx(s) s / BLOCK_SIZE #define ri register int #define FAST __attribute((optimize("Ofast"))) struct Student { int id, score, grade, gender; Student *nextH, *preH, *nextS, *preS; Student() {} Student(int id, int score, int grade, int gender) : id(id), score(score), grade(grade), gender(gender), nextH(0), preH(0), nextS(0), preS(0) {} } sArr[MAX_S], *hashTB[MAX_S], *scoreTB[2][3][NUM_BLOCK]; int sCnt; FAST Student* newStudent(int id, int score, int grade, int gender) { sArr[sCnt] = Student(id, score, grade, gender); return &sArr[sCnt++]; } FAST bool cmp(Student* a, Student* b) { // < if(a->score == b->score) return a->id < b->id; return a->score < b->score; } FAST void hPush(Student* s, int iH) { s->nextH = hashTB[iH]; if(hashTB[iH]) { hashTB[iH]->preH = s; } hashTB[iH] = s; } FAST bool hFind(Student*& res, int id, int iH) { for(Student* s = hashTB[iH]; s; s = s->nextH) { if(s->id == id) { res = s; return true; } } return false; } FAST void hDel(Student* s, int hIdx) { if(hashTB[hIdx] == s) { hashTB[hIdx] = s->nextH; } if(s->preH) { s->preH->nextH = s->nextH; } if(s->nextH) { s->nextH->preH = s->preH; } } FAST void sPush(Student* s, int gender, int grade) { ri idx = getScoreIdx(s->score); if(!scoreTB[gender][grade][idx]) { scoreTB[gender][grade][idx] = s; return; } Student* first = scoreTB[gender][grade][idx]; if(cmp(s, first)) { scoreTB[gender][grade][idx] = s; s->nextS = first; first->preS = s; return; } // s < i Student* mMax; for(Student* i = scoreTB[gender][grade][idx]; i; i = i->nextS) { if(cmp(s, i)) { s->preS = i->preS; if(i->preS) { i->preS->nextS = s; } s->nextS = i; i->preS = s; return; } mMax = i; } mMax->nextS = s; s->preS = mMax; } FAST void sDel(Student* s) { int idx = getScoreIdx(s->score); if(scoreTB[s->gender][s->grade][idx] == s) { scoreTB[s->gender][s->grade][idx] = s->nextS; } if(s->preS) { s->preS->nextS = s->nextS; } if(s->nextS) { s->nextS->preS = s->preS; } } FAST bool sFindHigher(Student*& res, int score, int gender, int grade) { ri idx = getScoreIdx(score) - 1; while(++idx < NUM_BLOCK && !scoreTB[gender][grade][idx]) {} if(idx == NUM_BLOCK) return false; for(Student* s = scoreTB[gender][grade][idx]; s; s = s->nextS) { if(s->score >= score) { res = s; return true; } } while(++idx < NUM_BLOCK && !scoreTB[gender][grade][idx]) {} if(idx == NUM_BLOCK) return false; res = scoreTB[gender][grade][idx]; return true; } FAST int findHighest(int gender, int grade) { ri idx = NUM_BLOCK; while(!scoreTB[gender][grade][--idx]) {} Student* max; for(Student* s = scoreTB[gender][grade][idx]; s; s = s->nextS) { max = s; } return max->id; } FAST int findLowest(int gender, int grade) { ri idx = -1; while(++idx < NUM_BLOCK && !scoreTB[gender][grade][idx]) {} if(idx == NUM_BLOCK) return 0; return scoreTB[gender][grade][idx]->id; } FAST void init() { sCnt = 0; for(ri i = 0; i < MAX_S; i++) { hashTB[i] = 0; } for(ri i = 0; i < 2; i++) { for(ri k = 0; k < 3; k++) { for(ri l = 0; l < NUM_BLOCK; l++) { scoreTB[i][k][l] = 0; } } } } FAST int add(int mId, int mGrade, char mGender[7], int mScore) { int gender = mGender[0] != 'm'; int grade = mGrade - 1; Student* s = newStudent(mId, mScore, grade, gender); hPush(s, getHashIdx(mId)); sPush(s, gender, grade); return findHighest(gender, grade); } FAST int remove(int mId) { Student* s; int hIdx = getHashIdx(mId); if(!hFind(s, mId, hIdx)) { return 0; } hDel(s, hIdx); sDel(s); return findLowest(s->gender, s->grade); } FAST void mQuery(Student*& res, int mGradeCnt, int mGrade[], int gender, int mScore) { int grade; Student* s; for(ri i = 0; i < mGradeCnt; i++) { grade = mGrade[i] - 1; if(sFindHigher(s, mScore, gender, grade)) { if(res == 0) { res = s; } else if(cmp(s, res)) { res = s; } } } } FAST int query(int mGradeCnt, int mGrade[], int mGenderCnt, char mGender[][7], int mScore) { int gender = mGender[0][0] != 'm'; Student *res = 0; mQuery(res, mGradeCnt, mGrade, gender, mScore); if(mGenderCnt == 2) { gender = 1 - gender; mQuery(res, mGradeCnt, mGrade, gender, mScore); } if(!res) return 0; return res->id; }
Editor is loading...