#include <iostream>
#include <map>
#include <vector>
#include <string>
#include <algorithm>
#include <sstream>
#include <iomanip>
#include <climits>
using namespace std;
// Helper function: Convert time in "hh:mmAM/PM" to minutes since midnight
int convertTimeToMinutes(const string& time) {
int hours = stoi(time.substr(0, time.find(':')));
int minutes = stoi(time.substr(time.find(':') + 1, 2));
string ampm = time.substr(time.size() - 2);
if (ampm == "PM" && hours != 12) hours += 12;
if (ampm == "AM" && hours == 12) hours = 0;
return hours * 60 + minutes;
}
// Function to process logs and organize entries and exits
map<int, map<int, pair<vector<int>, vector<int>>>> processLogs(
const vector<tuple<int, string, string, string>>& logs) {
map<int, map<int, pair<vector<int>, vector<int>>>> employeeLogs;
for (const auto& [employeeID, action, location, time] : logs) {
// Filter only logs with "room" in the location
if (location.find("room") == string::npos) continue;
int roomNumber = stoi(location.substr(4)); // Extract room number
int timeInMinutes = convertTimeToMinutes(time);
if (action == "enters") {
employeeLogs[employeeID][roomNumber].first.push_back(timeInMinutes);
} else if (action == "exits") {
employeeLogs[employeeID][roomNumber].second.push_back(timeInMinutes);
}
}
// Sort entries and exits for every room
for (auto& [employeeID, rooms] : employeeLogs) {
for (auto& [roomNumber, logs] : rooms) {
sort(logs.first.begin(), logs.first.end()); // Sort entries
sort(logs.second.begin(), logs.second.end()); // Sort exits
}
}
return employeeLogs;
}
// Function to calculate work done and consistency
pair<int, bool> calculateWorkDoneAndConsistency(
const map<int, map<int, pair<vector<int>, vector<int>>>>& employeeLogs,
map<int, map<int, int>>& workDonePerRoom, int employeeID) {
int totalWorkDone = 0;
bool isInconsistent = false;
for (const auto& [roomNumber, logs] : employeeLogs.at(employeeID)) {
const auto& entries = logs.first;
const auto& exits = logs.second;
vector<bool> entryUsed(entries.size(), false);
vector<bool> exitUsed(exits.size(), false);
int roomWorkDone = 0;
// Map exits to the nearest prior entry
for (size_t j = 0; j < exits.size(); ++j) {
for (size_t i = 0; i < entries.size(); ++i) {
if (!entryUsed[i] && entries[i] < exits[j]) {
roomWorkDone += exits[j] - entries[i];
entryUsed[i] = true;
exitUsed[j] = true;
break;
}
}
}
// Check if unmatched entries or exits remain
if (any_of(entryUsed.begin(), entryUsed.end(), [](bool used) { return !used; }) ||
any_of(exitUsed.begin(), exitUsed.end(), [](bool used) { return !used; })) {
isInconsistent = true;
}
totalWorkDone += roomWorkDone;
workDonePerRoom[employeeID][roomNumber] = roomWorkDone;
}
return {totalWorkDone, isInconsistent};
}
// Main function
int main() {
int n;
cin >> n;
vector<tuple<int, string, string, string>> logs(n);
for (int i = 0; i < n; ++i) {
int employeeID;
string action, location, time;
cin >> employeeID >> action >> location >> time;
logs[i] = {employeeID, action, location, time};
}
int suspectID;
cin >> suspectID;
// Step 1: Sort logs and organize data
sort(logs.begin(), logs.end(), [](const auto& a, const auto& b) {
if (get<0>(a) != get<0>(b)) return get<0>(a) < get<0>(b);
return get<2>(a) < get<2>(b);
});
auto employeeLogs = processLogs(logs);
// Step 2: Calculate work done and consistency for each employee
map<int, map<int, int>> workDonePerRoom;
map<int, pair<int, bool>> results; // {EmployeeID: {TotalWorkDone, IsInconsistent}}
for (const auto& [employeeID, _] : employeeLogs) {
results[employeeID] = calculateWorkDoneAndConsistency(employeeLogs, workDonePerRoom, employeeID);
}
// Step 3: Print individual employee status
cout << "Employee Status:\n";
for (const auto& [employeeID, result] : results) {
const auto& [totalWorkDone, isInconsistent] = result;
cout << "Employee ID: " << employeeID << "\n";
cout << " Consistency: " << (isInconsistent ? "Inconsistent" : "Consistent") << "\n";
cout << " Total Work Done: " << totalWorkDone << " minutes\n";
cout << " Work Done by Room:\n";
for (const auto& [room, work] : workDonePerRoom[employeeID]) {
cout << " room" << room << ": " << work << " minutes\n";
}
cout << "\n";
}
// Step 4: Determine result for suspect
bool suspectInconsistent = results[suspectID].second;
int suspectWork = results[suspectID].first;
int leastWork = INT_MAX;
bool otherInconsistentWithLessWork = false;
for (const auto& [employeeID, result] : results) {
const auto& [workDone, isInconsistent] = result;
if (workDone < leastWork) leastWork = workDone;
if (employeeID != suspectID && isInconsistent && workDone < suspectWork) {
otherInconsistentWithLessWork = true;
}
}
if (suspectInconsistent || otherInconsistentWithLessWork) {
cout << "Cannot be determined\n";
} else if (suspectWork == leastWork) {
cout << "Yes\n";
} else {
cout << "No\n";
}
return 0;
}