Untitled

mail@pastecode.io avatar
unknown
plain_text
a year ago
17 kB
10
Indexable
------------MAIN--------------

#ifndef _CRT_SECURE_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS
#endif

#include <stdio.h>

#define CMD_INIT				(100)
#define CMD_WRITE_MESSAGE		(200)
#define CMD_COMMENT_TO			(300)
#define CMD_ERASE				(400)
#define CMD_GET_BEST_MESSAGES	(500)
#define CMD_GET_BEST_USERS		(600)

#define MAXL	(10)	

extern void init();
extern int writeMessage(char mUser[], int mID, int mPoint);
extern int commentTo(char mUser[], int mID, int mTargetID, int mPoint);
extern int erase(int mID);
extern void getBestMessages(int mBestMessageList[]);
extern void getBestUsers(char mBestUserList[][MAXL + 1]);

static int mstrcmp(char a[], char b[])
{
	int idx = 0;
	while (a[idx] != '\0' && a[idx] == b[idx])
		++idx;
	return a[idx] - b[idx];
}

static bool run()
{
	int Q;
	int mID, mTargetID, mPoint;
	char mUser[MAXL + 1];
	char mBestUserList[5][MAXL + 1];
	int mBestMessageList[5];

	int ret = -1, ans;

	scanf("%d", &Q);

	bool okay = false;

	for (int q = 0; q < Q; ++q)
	{
		int cmd;
		scanf("%d", &cmd);
		switch(cmd)
		{
		case CMD_INIT:
			init();
			okay = true;
			break;
		case CMD_WRITE_MESSAGE:
			scanf("%s %d %d", mUser, &mID, &mPoint);
			ret = writeMessage(mUser, mID, mPoint);
			scanf("%d", &ans);
			if (ret != ans)
				okay = false;
			break;
		case CMD_COMMENT_TO:
			scanf("%s %d %d %d", mUser, &mID, &mTargetID, &mPoint);
			ret = commentTo(mUser, mID, mTargetID, mPoint);
			scanf("%d", &ans);
			if (ret != ans)
				okay = false;
			break;
		case CMD_ERASE:
			scanf("%d", &mID);
			ret = erase(mID);
			scanf("%d", &ans);
			if (ret != ans)
				okay = false;
			break;
		case CMD_GET_BEST_MESSAGES:
			getBestMessages(mBestMessageList);
			for (int i = 0; i < 5; ++i)
			{
				scanf("%d", &ans);
				if (mBestMessageList[i] != ans)
					okay = false;
			}
			break;
		case CMD_GET_BEST_USERS:
			getBestUsers(mBestUserList);
			for (int i = 0; i < 5; ++i)
			{
				scanf("%s", mUser);
				if (mstrcmp(mBestUserList[i], mUser) != 0)
					okay = false;
			}
			break;
		default:
			okay = false;
			break;
		}
	}

	return okay;
}

int main()
{
	setbuf(stdout, NULL);
	freopen("sample_input.txt", "r", stdin);

	int TC, MARK;

	scanf("%d %d", &TC, &MARK);
	for (int tc = 1; tc <= TC; ++tc)
	{
		int score = run() ? MARK : 0;
		printf("#%d %d\n", tc, score);
	}

	return 0;
}

--------------USER----------------------

#define MAXL	(10)
#define MAX_USER 10007
#define MAX_MESSAGE 50007
#define HASH_SIZE 20007
#define HEAP_SIZE 50007
#define ull unsigned long long

class Node{
public:
	ull id;
	Node* hashNext;
	int heapIdx;
	bool deleted;
	int point;
	int totalPoints;
	
	bool operator==(const Node& o){
		return (o.deleted? false : (o.id == id));
	}

	bool operator<(const Node& o){
		return ((totalPoints == o.totalPoints)? id > o.id : totalPoints < o.totalPoints);
	}
};

class Message : public Node{
public:
	Message* parent;
	Message* child;
	Message* next;
	int type;
	Node* user;

	void init(int mId, int mPoint, int mType, Node* mUser, Message* mParent){
		id = mId;
		point = mPoint;
		totalPoints = mPoint;
		type = mType;
		user = mUser;
		parent = mParent;
		hashNext = 0;
		next = child = 0;
		heapIdx = deleted = 0;
	}
};

class User : public Node{
public:
	char sName[11];
	int length;
	void init(char* str){
		heapIdx = totalPoints = 0;
		deleted = false;
		hashNext = 0;
		id = getHash(str);
		length = 0;
		while(str[length] != '\0'){
			sName[length] = str[length];
			length++;
		}
		sName[length++] = '\0';
	}

	//ull getHash(char* str){
	//	ull ret = 0;
	//	while(*str != '\0'){
	//		ret = ret * 31 + (*str - 'a' + 1);
	//		str++;
	//	}
	//	return ret;
	//}
	ull getHash(char* s)
    {
        ull ret = 0;
        int pow = 9;
        while (*s != '\0')
        {
            ull c = (*s - 'a' + 1);
            ret = (ret | (c << (pow * 5)));
            pow--;
            s++;
        }
        return ret;
    }
};

class HashMap{
public:
	Node* hm[HASH_SIZE];
	void reset(){
		for(int i = 0 ; i < HASH_SIZE; i++){
			hm[i] = 0;
		}
	}
	void insert(Node* node){
		int h = node->id % HASH_SIZE;
		node->hashNext = hm[h];
		hm[h] = node;
	}
	Node* get(Node* node){
		int h = node->id % HASH_SIZE;
		Node* n = hm[h];
		while(n && !(*node == *n)) n = n->hashNext; 
		return n;
	}
};

class IndexedHeap{
public:
	Node* hp[HEAP_SIZE];
	int idx;
	
	void reset() {idx = 0;}
	void down(Node* node){
		int id = node->heapIdx;
		int child = 2*id + 1;
		while(child < idx){
			if(child + 1 < idx && (*hp[child] < *hp[child+1])) child++;
			if(*hp[child] < *node) break;

			hp[id] = hp[child];
			hp[id]->heapIdx = id;
			id = child;
			child = 2*id + 1;
		}
		hp[id] = node;
		node->heapIdx = id;
	}
	void up(Node* node){
		int id = node->heapIdx;
		while(id){
			int parent = (id - 1)/2;
			if(*node < *hp[parent]) break;
			hp[id] = hp[parent];
			hp[id]->heapIdx = id;
			id = parent;
		}
		hp[id] = node;
		node->heapIdx = id;
	}
	void push(Node* node){
		node->heapIdx = idx;
		hp[idx] = node;
		up(hp[idx++]);
	}
	void update(Node* node){
		int id = node->heapIdx;
		down(hp[id]);
		up(hp[id]);
	}
	Node* pop(){
		Node* node  = hp[0];
		hp[0] = hp[--idx];
		hp[0]->heapIdx = 0;
		down(hp[0]);
		return node;
	}
};

Message messages[MAX_MESSAGE];
int msgIdx;

User users[MAX_USER];
int userIdx;

HashMap messageHm, userHm;
IndexedHeap messageHp, userHp;

void init()
{
	msgIdx = userIdx = 2;
	messageHm.reset();
	userHm.reset();
	messageHp.reset();
	userHp.reset();
	return;
}

Node* getUser(char* mUser)
{
    auto& user = users[userIdx];
    user.init(mUser);
	Node* ptr = userHm.get(&user);
    if (ptr == 0)
    {
		userHm.insert(&user);
		userHp.push(&user);
        ptr = &user;
        userIdx++;
    }
    return ptr;
}
 
int writeMessage(char mUser[], int mID, int mPoint)
{
    auto user = getUser(mUser);
	user->totalPoints += mPoint;
	userHp.update(user);
 
	auto msg = &messages[msgIdx++];
    msg->init(mID, mPoint, 0, user, 0);
	messageHp.push(msg);
	messageHm.insert(msg);
 
	return user->totalPoints;
}

int commentTo(char mUser[], int mID, int mTargetID, int mPoint)
{
	auto user = getUser(mUser);
    user->totalPoints += mPoint;
    userHp.update(user);

	messages[1].id = mTargetID;
	Message* pmsg = (Message*)messageHm.get(&messages[1]);
	Message* message = &messages[msgIdx++];
	message->init(mID, mPoint, pmsg->type+1, user, pmsg);
	messageHm.insert(message);

	if(pmsg->child == 0) pmsg->child = message;
	else{
		Message* m = pmsg->child;
		pmsg->child = message;
		message->next = m;
	}

	pmsg->totalPoints += mPoint;
	if(pmsg->parent) {
		pmsg = pmsg->parent;
		pmsg->totalPoints += mPoint;
	}
	messageHp.update(pmsg);
	return pmsg->totalPoints;
}

int erase(int mID)
{
	messages[1].id = mID;
	Message* msg = (Message*)messageHm.get(&messages[1]);

	msg->user->totalPoints -= msg->point;
	userHp.update(msg->user);
	msg->deleted = true;

	if(msg->child){
		Message* ch1 = msg->child;
		while(ch1){
			if(!ch1->deleted){
				ch1->user->totalPoints -= ch1->point;
				userHp.update(ch1->user);
				ch1->deleted = true;
				if(ch1->child){
					Message* ch2 = ch1->child;
					while(ch2){
						if(!ch2->deleted){
							ch2->user->totalPoints-= ch2->point;
							userHp.update(ch2->user);
							ch2->deleted = true;
						}
						ch2 = ch2->next;
					}
				}
			}
			ch1=ch1->next;
		}
	}

	if(msg->type == 0) return msg->user->totalPoints;

	int p = msg->totalPoints;
	while(msg->type != 0){
		msg = msg->parent;
		msg ->totalPoints -= p;
	}
	messageHp.update(msg);
	return msg->totalPoints;
}

void getBestMessages(int mBestMessageList[])
{
	int i = 0;
	Message* msg[5];
	while(i < 5){
		msg[i] = (Message*) messageHp.pop();
		if(msg[i]->deleted) continue;
		mBestMessageList[i] = msg[i]->id;
		i++;
	}
	while(i > 0) messageHp.push(msg[--i]);
}

void getBestUsers(char mBestUserList[][MAXL + 1])
{
	int i = 0;
	User* user[5];
	while(i < 5){
		user[i] = (User*)userHp.pop();
		if(user[i]->deleted) continue;

		auto u = user[i];
		for(int j = 0; j < u->length; j++) mBestUserList[i][j] = u->sName[j];
		i++;
	}
	while(i > 0) userHp.push(user[--i]);
	return;
}

-------------------INPUT---------------------------

#define MAX_POST 50001
#define MAX_USER 10001
#define MAX_HASH1 10007
#define MAX_HASH2 50021
#define MAX_L 11
  
//String utils:
void strCpy(char *t, char *s)
{
    while (*t++ = *s++)
        ;
}
  
long long hash(char* name)
{
    long long ret = 0;
    for (register int i = 0; name[i]; i++)
        ret += (long long)(name[i] - 96) << (5 * (9 - i));
    return ret;
}
  
struct BasicInfo {//Common info of all objects
    long long id; //for users, info id is hash value of their name; for messages, comments, replies, info id is their id.
    int totalPoint;
    int objectIdx; //index of objects in pool arrays
    BasicInfo* next; //For hash map
    int heapIdx; //For heap
} infos[MAX_POST + MAX_USER];
int objectCnt;
  
struct User {
    char name[MAX_L];
    BasicInfo* info;
} users[MAX_USER];
int userNum;
  
struct Post { //A post can be message, comment or reply
    int point;
    BasicInfo* info;
    Post* parent;
    User* user;
  
    //For linked list
    Post* next; 
    Post* firstChild;   
} posts[MAX_POST];
int postNum;
  
//Heaps
BasicInfo* userInfoHeap[MAX_USER];
int userHeapSize;
BasicInfo* postInfoHeap[MAX_POST];
int postHeapSize;
  
bool isBetter(BasicInfo* info1, BasicInfo* info2)
{
    return info1->totalPoint > info2->totalPoint || (info1->totalPoint == info2->totalPoint && info1->id < info2->id);
}
  
void upHeapify(BasicInfo* heap[], int pos)
{
    register BasicInfo* curr = heap[pos];
    for( ; pos > 1 && isBetter(curr, heap[pos >> 1]); pos >>= 1) {
        heap[pos] = heap[pos >> 1];
        heap[pos]->heapIdx = pos;
    }
    heap[pos] = curr;
    heap[pos]->heapIdx = pos;
}
  
void downHeapify(BasicInfo* heap[], int size, int pos)
{
    register BasicInfo* curr = heap[pos];
    register int child;
    while ((child = pos << 1) <= size) {
        if (child < size && isBetter(heap[child + 1], heap[child]))
            child++;
        if (isBetter(heap[child], curr)) {
            heap[pos] = heap[child];
            heap[pos]->heapIdx = pos;
            pos = child;
        } else break;
    }
    heap[pos] = curr;
    heap[pos]->heapIdx = pos;
}
  
void heapPush(BasicInfo* heap[], int &size, BasicInfo* info)
{
    heap[++size] = info;
    upHeapify(heap, size);
}
  
void heapUpdate(BasicInfo* heap[], int size, BasicInfo* info)
{
    register int pos = info->heapIdx;
    upHeapify(heap, pos);
    downHeapify(heap, size, pos);
}
  
void heapRemove(BasicInfo* heap[], int &size, BasicInfo* info)
{
    register int pos = info->heapIdx;
    heap[pos] = heap[size--];
    heap[pos]->heapIdx = pos;
    heapUpdate(heap, size, heap[pos]);
}
  
BasicInfo* heapPop(BasicInfo* heap[], int &size)
{
    BasicInfo* ret = heap[1];
    heapRemove(heap, size, heap[1]);
    return ret;
}
  
//HashMaps
BasicInfo* userInfoMap[MAX_HASH1];
BasicInfo* postInfoMap[MAX_HASH2];
  
Post* findPost(int postId)
{
    for (BasicInfo* info = postInfoMap[postId % MAX_HASH2]; info; info = info->next)
        if (postId == info->id)
            return &posts[info->objectIdx];
    return nullptr;
}
  
User* findUser(char *name)
{
    long long hashVal = hash(name);
    for (BasicInfo* info = userInfoMap[hashVal % MAX_HASH1]; info; info = info->next)
        if (hashVal == info->id)
            return &users[info->objectIdx];
      
    //If user not exist, create new user and user info
    BasicInfo* info = &infos[objectCnt++];
    info->id = hashVal;
    info->objectIdx = userNum;
    info->totalPoint = 0;
    //Add to hash map
    register int idx = hashVal % MAX_HASH1;
    info->next = userInfoMap[idx];
    userInfoMap[idx] = info;
    //Add to end of heap, will be updated later
    userInfoHeap[++userHeapSize] = info;
    info->heapIdx = userHeapSize;
    //Create new user
    strCpy(users[userNum].name, name);
    users[userNum].info = info;
    return &users[userNum++];
}
  
int addNewPost(User* user, int mID, int mPoint, Post* mParent)
{
    user->info->totalPoint += mPoint;
    heapUpdate(userInfoHeap, userHeapSize, user->info);
      
    //Create new post info and add to hash map
    BasicInfo* postInfo = &infos[objectCnt++];
    postInfo->id = mID;
    postInfo->totalPoint = mPoint;
    postInfo->objectIdx = postNum;
    register int idx = mID % MAX_HASH2;
    postInfo->next = postInfoMap[idx];
    postInfoMap[idx] = postInfo;
      
    //Create new post
    Post* post = &posts[postNum++];
    post->info = postInfo;
    post->point = mPoint;
    post->user = user;
    post->firstChild = nullptr;
    post->parent = mParent;
    if (mParent) { //this post is a comment or reply
        post->next = mParent->firstChild;
        mParent->firstChild = post;
        mParent->info->totalPoint += mPoint;
        if (mParent->parent) { //this is a reply
            mParent = mParent->parent;
            mParent->info->totalPoint += mPoint;
        }
        heapUpdate(postInfoHeap, postHeapSize, mParent->info);
        return mParent->info->totalPoint;
    }
    //this post is a message
    heapPush(postInfoHeap, postHeapSize, postInfo);
    post->next = nullptr;
    return user->info->totalPoint;
}
  
void init()
{
    objectCnt = userNum = postNum = userHeapSize = postHeapSize = 0;
    for (register int i = 0; i < MAX_HASH1; i++)
        userInfoMap[i] = nullptr;
    for (register int i = 0; i < MAX_HASH2; i++)
        postInfoMap[i] = nullptr;
}
  
int writeMessage(char mUser[], int mID, int mPoint)
{
    User* user = findUser(mUser);   
    return addNewPost(user, mID, mPoint, nullptr);
}
  
int commentTo(char mUser[], int mID, int mTargetID, int mPoint)
{
    User* user = findUser(mUser);
    Post* target = findPost(mTargetID); 
    return addNewPost(user, mID, mPoint, target);
}
  
//When erasing post, traversal all descendants and update their user's point
void updateUserPoint(Post* post)
{
    post->user->info->totalPoint -= post->point;
    heapUpdate(userInfoHeap, userHeapSize, post->user->info);
  
    for (register Post* child = post->firstChild; child; child = child->next)
        updateUserPoint(child);
}
  
int erase(int mID)
{
    Post* post = findPost(mID); 
    updateUserPoint(post);
  
    Post* parent = post->parent;
    if (parent) {//this post is a comment or reply
        //delete from parent's list
        if (post == parent->firstChild)
            parent->firstChild = post->next;
        else {
            for (register Post* i = parent->firstChild; i->next; i = i->next) {
                if (post == i->next) {
                    i->next = i->next->next;
                    break;
                }
            }
        }
  
        parent->info->totalPoint -= post->info->totalPoint;
        if (parent->parent) { //this post is a reply
            parent = parent->parent;
            parent->info->totalPoint -= post->info->totalPoint;     
        }
        heapUpdate(postInfoHeap, postHeapSize, parent->info);
        return parent->info->totalPoint;
    }
    //this is a message
    heapRemove(postInfoHeap, postHeapSize, post->info);
    return post->user->info->totalPoint;
}
  
BasicInfo* bestInfos[5];
  
void getBestMessages(int mBestMessageList[])
{
    for (register int i = 0; i < 5; i++) {
        bestInfos[i] = heapPop(postInfoHeap, postHeapSize);
        mBestMessageList[i] = bestInfos[i]->id;
    }
    for (register int i = 0; i < 5; i++) 
        heapPush(postInfoHeap, postHeapSize, bestInfos[i]);
}
  
void getBestUsers(char mBestUserList[][MAX_L])
{
    for (register int i = 0; i < 5; i++) {
        bestInfos[i] = heapPop(userInfoHeap, userHeapSize);
        strCpy(mBestUserList[i], users[bestInfos[i]->objectIdx].name);
    }
    for (register int i = 0; i < 5; i++) 
        heapPush(userInfoHeap, userHeapSize, bestInfos[i]);
}