Easy HashMap solution || HashSet || Sorting || Java || Python || C++
IntuitionFirst, we will sort the mentions array based on the timestamp of the events. If two events have the same timestamp, we prioritize "OFFLINE" events. We
# Intuition
First, we will sort the mentions array based on the timestamp of the events. If two events have the same timestamp, we prioritize "OFFLINE" events. We need to maintain the current time and store the mapping of each userId to the time when they went offline. Additionally, we will keep track of users who are currently online in a Set.

Whenever a new event occurs, we will update the current time to the timestamp of the event. The event handling is as follows:

- "ALL" Event: Increment the mention count for all users.
- "HERE" Event: Iterate through the offlineMap and mark users as online if their offline time is older than 60 minutes. Then, iterate through all online users and increment their mention count.
- Specific User Mentions: For messages targeting specific users, check the offlineMap to mark users as online if their offline time is older than 60 minutes. If the user is online, increment their mention count.

# Complexity
- Time complexity:
1. ElogE for sorting.
2. E*N for iterating all the events for an event 

##### Total : O(ElogE + E*N) where E is the number of events and N is the number of users.

- Space complexity:
O(n) for storing the information for n users

# Code
```java []
class Solution {
    public int[] countMentions(int numberOfUsers, List<List<String>> events) {
        int[] mentions = new int[numberOfUsers];
        Map<Integer, Integer> offlineMap = new HashMap<>();
        Set<Integer> onlineUsers = new HashSet<>();
        for (int i = 0; i < numberOfUsers; i++) {
            onlineUsers.add(i);
        }

        events.sort((a, b) -> {
            int timeA = Integer.parseInt(a.get(1));
            int timeB = Integer.parseInt(b.get(1));
            if (timeA != timeB) {
                return timeA - timeB;
            }
            return a.get(0).equals("OFFLINE") ? -1 : 1;
        });

        int currTime = 0;

        for (List<String> event : events) {
            String eventType = event.get(0);
            int timestamp = Integer.parseInt(event.get(1));
            String data = event.get(2);

            if (timestamp > currTime) {
                currTime = timestamp;

                List<Integer> toRemove = new ArrayList<>();

                for (Map.Entry<Integer, Integer> entry : offlineMap.entrySet()) {
                    int userId = entry.getKey();
                    int offlineTime = entry.getValue();

                    if (currTime - offlineTime >= 60) {
                        toRemove.add(userId);
                        onlineUsers.add(userId);
                    }
                }

                for (int userId : toRemove) {
                    offlineMap.remove(userId);
                }
            }

            if (eventType.equals("OFFLINE")) {
                int userId = Integer.parseInt(data);
                onlineUsers.remove(userId);
                offlineMap.put(userId, currTime);
            } else if (eventType.equals("MESSAGE")) {
                if (data.equals("ALL")) {
                    for (int i = 0; i < numberOfUsers; i++) {
                        mentions[i]++;
                    }
                } else if (data.equals("HERE")) {
                    List<Integer> toRemove = new ArrayList<>();
                    for (Map.Entry<Integer, Integer> entry : offlineMap.entrySet()) {
                        int userId = entry.getKey();
                        int offlineTime = entry.getValue();

                        if (currTime - offlineTime >= 60) {
                            toRemove.add(userId);
                            onlineUsers.add(userId);
                        }
                    }

                    for (int userId : toRemove) {
                        offlineMap.remove(userId);
                    }

                    for (int userId : onlineUsers) {
                        mentions[userId]++;
                    }
                } else {
                    String[] tokens = data.split(" ");
                    for (String token : tokens) {
                        if (token.startsWith("id")) {
                            int userId = Integer.parseInt(token.substring(2));
                            mentions[userId]++;
                        }
                    }
                }
            }
        }

        return mentions;
    }
}

```
```C++ []
class Solution {
public:
    vector<int> countMentions(int numberOfUsers, vector<vector<string>>& events) {
        vector<int> mentions(numberOfUsers, 0);
        unordered_map<int, int> offlineMap;
        unordered_set<int> onlineUsers;
        for (int i = 0; i < numberOfUsers; i++) {
            onlineUsers.insert(i);
        }

        sort(events.begin(), events.end(), [](vector<string>& a, vector<string>& b) {
            int timeA = stoi(a[1]);
            int timeB = stoi(b[1]);
            if (timeA != timeB) return timeA < timeB;
            return a[0] == "OFFLINE" ? true : false;
        });

        int currTime = 0;

        for (auto& event : events) {
            string eventType = event[0];
            int timestamp = stoi(event[1]);
            string data = event[2];

            if (timestamp > currTime) {
                currTime = timestamp;

                vector<int> toRemove;
                for (auto& entry : offlineMap) {
                    int userId = entry.first;
                    int offlineTime = entry.second;

                    if (currTime - offlineTime >= 60) {
                        toRemove.push_back(userId);
                        onlineUsers.insert(userId);
                    }
                }

                for (int userId : toRemove) {
                    offlineMap.erase(userId);
                }
            }

            if (eventType == "OFFLINE") {
                int userId = stoi(data);
                onlineUsers.erase(userId);
                offlineMap[userId] = currTime;
            } else if (eventType == "MESSAGE") {
                if (data == "ALL") {
                    for (int i = 0; i < numberOfUsers; i++) {
                        mentions[i]++;
                    }
                } else if (data == "HERE") {
                    vector<int> toRemove;
                    for (auto& entry : offlineMap) {
                        int userId = entry.first;
                        int offlineTime = entry.second;

                        if (currTime - offlineTime >= 60) {
                            toRemove.push_back(userId);
                            onlineUsers.insert(userId);
                        }
                    }

                    for (int userId : toRemove) {
                        offlineMap.erase(userId);
                    }

                    for (int userId : onlineUsers) {
                        mentions[userId]++;
                    }
                } else {
                    stringstream ss(data);
                    string token;
                    while (ss >> token) {
                        if (token.substr(0, 2) == "id") {
                            int userId = stoi(token.substr(2));
                            mentions[userId]++;
                        }
                    }
                }
            }
        }

        return mentions;
    }
};

```
``` Python []
class Solution:
    def countMentions(self, numberOfUsers: int, events: List[List[str]]) -> List[int]:
        mentions = [0] * numberOfUsers
        offlineMap = {}
        onlineUsers = set(range(numberOfUsers))

        events.sort(key=lambda x: (int(x[1]), x[0] == "OFFLINE"))

        currTime = 0

        for event in events:
            eventType = event[0]
            timestamp = int(event[1])
            data = event[2]

            if timestamp > currTime:
                currTime = timestamp

                toRemove = []
                for userId, offlineTime in offlineMap.items():
                    if currTime - offlineTime >= 60:
                        toRemove.append(userId)
                        onlineUsers.add(userId)

                for userId in toRemove:
                    del offlineMap[userId]

            if eventType == "OFFLINE":
                userId = int(data)
                onlineUsers.remove(userId)
                offlineMap[userId] = currTime
            elif eventType == "MESSAGE":
                if data == "ALL":
                    for i in range(numberOfUsers):
                        mentions[i] += 1
                elif data == "HERE":
                    toRemove = []
                    for userId, offlineTime in offlineMap.items():
                        if currTime - offlineTime >= 60:
                            toRemove.append(userId)
                            onlineUsers.add(userId)

                    for userId in toRemove:
                        del offlineMap[userId]

                    for userId in onlineUsers:
                        mentions[userId] += 1
                else:
                    for token in data.split():
                        if token.startswith("id"):
                            userId = int(token[2:])
                            mentions[userId] += 1

        return mentions
```

# UPVOTE IF IT HELPS
['Hash Table', 'Sorting', 'Python', 'C++', 'Java']