[Java] sort, queue
```Java []
class Solution{

public static int[] countMentions(int userNum, List<List<String>> events){
	Collections.sort(
		events,
		(cur, base) -> {
			if (!cur.get(1).equals(base.get(1))){
				return Integer.compare(
					Integer.parseInt(cur.get(1)),
					Integer.parseInt(base.get(1))
				);
			}else {
				return cur.get(0).equals("OFFLINE")? -1 : 1;
			}
		}
	);

	int[] userMentionedCnts = new int[userNum];

	//temp data
	boolean[] onlineUserSet = new boolean[userNum];
	Arrays.fill(onlineUserSet, true);

	var offlineUserAndValidTimeQueue = new ArrayDeque<Pair<Integer, Integer>>(userNum);

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

		while (
			!offlineUserAndValidTimeQueue.isEmpty() &&
			offlineUserAndValidTimeQueue.peekFirst().getValue() <= timestamp
		){
			onlineUserSet[offlineUserAndValidTimeQueue.remove().getKey()] = true;
		}

		switch (event.get(0)){
		case "MESSAGE":
			switch (event.get(2)){
			case "ALL":
				allMentionedCnt += 1;
				break;
			case "HERE":
				for (int i = 0; i < userNum; i += 1){
					if (onlineUserSet[i]){
						userMentionedCnts[i] += 1;
					}
				}
				break;
			default:
			{
				List<Integer> users = Arrays.stream(event.get(2).split(" "))
					.map(str -> Integer.parseInt(str.substring(2, str.length())))
					.collect(Collectors.toList());
				for (int user : users){
					userMentionedCnts[user] += 1;
				}
			}
			}
			break;
		case "OFFLINE":
		{
			int user = Integer.parseInt(event.get(2));

			onlineUserSet[user] = false;

			offlineUserAndValidTimeQueue.add(new Pair<>(user, timestamp + 60));
		}
			break;
		}
	}
	for (int i = 0; i < userNum; i += 1){
		userMentionedCnts[i] += allMentionedCnt;
	}

	return userMentionedCnts;
}

}
```
['Java']