#define MAXL (10)
#include <iostream>
#include <string>
#include <unordered_map>
#include <set>
#include <vector>
using namespace std;
struct user{
string name;
int point;
} User[10001];
struct CMPUSER{
bool operator()(user *a, user *b){
if(a->point != b->point) return a->point > b->point;
return a->name < b->name;
}
};
struct cmt{
int point;
int allPoint;
string user;
int id;
int parent;
vector<int>child;
} Cmt[50001];
struct CMPCMT{
bool operator()(cmt* a, cmt* b){
if(a->allPoint != b->allPoint) return a->allPoint > b->allPoint;
return a->id < b->id;
}
};
int idU, idC;
user* getUser(){
User[idU].point=0;
return &User[idU++];
}
cmt* getCmt(){
Cmt[idC].child.clear();
Cmt[idC].allPoint=0;
Cmt[idC].point=0;
return &Cmt[idC++];
}
set<cmt*, CMPCMT> sortCmt;
set<user*, CMPUSER> sortUser;
unordered_map<int, cmt*> hashCmt;
unordered_map<string, user*> hashUser;
void init()
{
idU=idC=0;
sortUser.clear();
sortCmt.clear();
hashCmt.clear();
hashUser.clear();
return;
}
int writeMessage(char mUser[], int mID, int mPoint)
{
user* u;
auto it=hashUser.find(mUser);
if(it == hashUser.end()){
u=getUser();
u->name=mUser;
hashUser[mUser]=u;
}
else{
u=it->second;
sortUser.erase(u);
}
u->point+=mPoint;
sortUser.insert(u);
cmt* c=getCmt();
c->id=mID, c->parent=mID, c->point=mPoint, c->user= mUser, c->allPoint=mPoint;
sortCmt.insert(c);
hashCmt[mID]=c;
return u->point;
}
int commentTo(char mUser[], int mID, int mTargetID, int mPoint)
{
user* u;
auto it=hashUser.find(mUser);
if(it == hashUser.end()){
u=getUser();
u->name=mUser;
hashUser[mUser]=u;
}
else{
u=it->second;
sortUser.erase(u);
}
u->point+=mPoint;
sortUser.insert(u);
cmt* newC= getCmt();
newC->allPoint=mPoint;
newC->point=mPoint;
newC->parent=mTargetID;
newC->id=mID;
newC->user=mUser;
hashCmt[mID]=newC;
cmt* target= hashCmt[mTargetID];
target->child.push_back(mID);
cmt* cur=target;
while(cur->id != cur->parent){
cur->allPoint+=mPoint;
cur=hashCmt[cur->parent];
}
sortCmt.erase(cur);
cur->allPoint+=mPoint;
sortCmt.insert(cur);
return cur->allPoint;
}
void delChild(int mID){
cmt* c=hashCmt[mID];
hashCmt.erase(mID);
sortCmt.erase(c);
sortUser.erase(hashUser[c->user]);
hashUser[c->user]->point-=c->point;
sortUser.insert(hashUser[c->user]);
if(c->child.size()==0) return;
for(auto it:c->child){
delChild(it);
}
}
int erase(int mID)
{
cmt* c=hashCmt[mID];
cmt* cur=hashCmt[c->parent];
while(cur->id != cur->parent){
cur->allPoint-=c->allPoint;
cur=hashCmt[cur->parent];
}
sortCmt.erase(cur);
cur->allPoint-=c->allPoint;
sortCmt.insert(cur);
delChild(mID);
if(c->parent == c->id) return hashUser[c->user]->point;
return cur->allPoint;
}
void getBestMessages(int mBestMessageList[])
{
int i=0;
for(auto it: sortCmt){
if(i==5) break;
mBestMessageList[i]=it->id;
}
return;
}
void getBestUsers(char mBestUserList[][MAXL + 1])
{
int i=0;
for(auto it: sortUser){
if(i==5) break;
mBestUserList[i]=it->name;
}
return;
}