Solution based on user class where mentions, status and timing are defined.
IntuitionWe need to sort events by time an dthen by type (offline first). After that we can move from event to event and in case of "HERE" type event check if a
# Intuition
We need to sort events by time an dthen by type (offline first). After that we can move from event to event and in case of "HERE" type event check if any users already returned online. To track user status one may use an array of a custom 'user' class.

# Approach
Code speaks for itself. If you see any improvements - you are welcome!

# Complexity
- Time complexity: O(user.Count*events.Count).
- Space complexity: O(user.Count).

# Code
```csharp []
public class Solution {
    public int _delay = 60;

    public int[] CountMentions(int n, IList<IList<string>> events_ini) {
        // Create new Users set;
        User[] userSet = new User[n];
        for(int i=0; i<n; i++) userSet[i] = new(0,0);
        // Sort events
        var events = new List<IList<string>>(events_ini);
        events.Sort(new EventComparer());
        // Check the sorting
        //for(int i=0; i<events.Count; i++) Console.WriteLine(events[i][1] + "_" + events[i][0] + "_" + events[i][2]);
        // Cycle through events
        int _time = 0;
        foreach(List<string> _event in events)
        {
            _time = Convert.ToInt32(_event[1]);
            if(_event[0]=="OFFLINE")
                userSet[Convert.ToInt32(_event[2])].SetOffline(_time + _delay);
            else if(_event[2]=="ALL")
                for(int i=0; i<n; i++) userSet[i].mentions++;
            else if(_event[2]=="HERE"){
                // Check all states
                for(int i=0; i<n; i++)
                    if(userSet[i].minute_On <= _time)
                        userSet[i].online = true;
                //Add all online
                for(int i=0; i<n; i++)
                    if(userSet[i].online) userSet[i].mentions++;
            }
            else {
                var ids = _event[2].Split(' ');
                foreach(string _s in ids)
                    userSet[Convert.ToInt32(_s.Replace("id", ""))].mentions++;
            }
        }
        // Compose the Answer
        int[] mentions = new int[n];
        for(int i=0; i<n; i++) mentions[i] = userSet[i].mentions;
        return mentions;
    }
}

public class User {
    public bool online {get; set;}
    public int minute_On {get; set;}
    public int mentions {get; set;} 
    
    public User(int min, int ment){
        this.online = true;
        this.minute_On = min;
        this.mentions = ment;
    }

    public void SetOffline(int delayTime){
        this.online = false;
        this.minute_On = delayTime;
    }
}

public class EventComparer : IComparer<IList<string>>{
    public int Compare(IList<string> a, IList<string> b){
        int m1 = Convert.ToInt32(a[1]), m2 = Convert.ToInt32(b[1]);
        int result = m1.CompareTo(m2);
        // If the first text fields are equal, compare the status filed, "OFFFLINE" is lexiografically bigger then "MESSAGE" (!)
        if (result == 0) result = string.Compare(b[0], a[0], StringComparison.Ordinal);
        return result;
    }
}
```
['C#']