#include<iostream>
#include<unordered_map>
#include<vector>
#include<cstring>
#include<utility>
#include<algorithm>
#include<set>
#define MAXL (10)
#define MAXC (10005)
#define MAXP (100)
using namespace std;
struct card
{
string word;
string key;
int playerCnt = 0;
}cards[MAXC];
struct Player
{
int id;
int score;
int cardscnt[MAXC];
bool playing;
}players[MAXP];
int Totalplayers;
struct cmp {
bool operator() (const int& a, const int& b)const {
if (cards[a].playerCnt == cards[b].playerCnt)
return cards[a].word < cards[b].word;
return cards[a].playerCnt > cards[b].playerCnt;
}
};
unordered_map<string, unordered_map<string, vector<int>>> mp;
void init(int N, char mWordList[][MAXL + 1], char mSubjectList[][MAXL + 1])
{
for (int i = 0; i < MAXP; i++) {
players[i].score = 0;
players[i].playing = false;
for (int j = 0; j < MAXC; j++)
players[i].cardscnt[j] = 0;
}
for (int i = 0; i < MAXC; i++) {
cards[i].playerCnt = 0;
}
Totalplayers = 0;
mp.clear();
for (int i = 0; i < N; i++) {
cards[i + 1].word = mWordList[i];
cards[i + 1].key = mSubjectList[i];
mp[cards[i + 1].key][cards[i + 1].word.substr(0, 1)].push_back(i + 1);
mp[cards[i + 1].key][cards[i + 1].word.substr(0, 2)].push_back(i + 1);
}
return;
}
void join(int mID, int M, int mcardsList[])
{
Totalplayers = mID;
players[mID].id = mID;
players[mID].playing = true;
players[mID].score = 0;
for (int i = 0; i < M; i++) {
if(players[mID].cardscnt[mcardsList[i]] == 0)
cards[mcardsList[i]].playerCnt += 1;
players[mID].cardscnt[mcardsList[i]]++;
}
return;
}
int playRound(char mBeginStr[], char mSubject[])
{
sort(mp[mSubject][mBeginStr].begin(), mp[mSubject][mBeginStr].end(), cmp());
int ans = 0;
unordered_map<int, vector<int>> cardsThrownByplayer;
for (int i = 1; i <= Totalplayers; i++) {
if (players[i].playing) {
for (auto it = mp[mSubject][mBeginStr].begin(); it != mp[mSubject][mBeginStr].end(); it++) {
if (players[i].cardscnt[*it] > 0) {
cardsThrownByplayer[*it].push_back(i);
players[i].cardscnt[*it]--;
if (players[i].cardscnt[*it] == 0)
cards[*it].playerCnt--;
break;
}
}
}
}
for (auto it = cardsThrownByplayer.begin(); it != cardsThrownByplayer.end(); it++) {
ans += it->first * it->second.size();
for (int i = 0; i < it->second.size(); i++) {
players[it->second[i]].score += (it->second.size() - 1) * (it->second.size() - 1);
}
}
return ans;
}
int leave(int mID)
{
int res = players[mID].score;
players[mID].playing = false;
for (int i = 0; i < MAXC; i++) {
if (players[mID].cardscnt[i] > 0) {
cards[i].playerCnt--;
}
}
return res;;
}