3433: 统计用户被提及情况
思路:排序+模拟
注意输入的 events 不保证是按时间顺序发生的,需要先排序。
按照时间戳 timestamp 从小到大排序,时间戳相同的,离线事件排在前面,因为题目要求「++状态变更++在所有相同时间发生的消息事件之前处理」。
然后模拟:
-
离线事件:用一个数组 onlineT 记录用户下次在线的时间戳(60 秒后)。如果当前时间戳>= onlineT[i],则表示用户 i 已在线。
-
消息事件:把相应用户的提及次数加一。
string& mention = e[2];

else{ // @id
int idx=0;
for(int i=0;i<mention.size();i++){
if(isdigit(mention[i])) idx=idx*10+(mention[i]-'0');
if(i+1==mention.size() || mention[i+1]==' '){
ans[idx]++;
idx=0;
}
}
}
-
isdigit(mention[i])是判断字符串mention第i个字符是不是 十进制数字字符 ('0'--'9') -
1 <= numberOfUsers <= 100 因此要考虑可能出现形似id12 的情况idx=idx*10+(mention[i]-'0')class Solution {
public:
vector<int> countMentions(int numberOfUsers, vector<vector<string>>& events) {
vector<int> ans(numberOfUsers);
vector<int> online_t(numberOfUsers,0);
// 按照时间戳从小到大排序,时间戳相同的,离线事件排在前面
//两两比较,["MESSAGE","10","id1 id0"],["OFFLINE","11","0"]
auto cmp=[](const vector<string>& lth,const vector<string>& rth){
int lth_tsp=stoi(lth[1]); //stoi适用于string转int
int rth_tsp=stoi(rth[1]);
if(lth_tsp!=rth_tsp) return lth_tsp<rth_tsp;
else return lth[0]>rth[0]; // "OFFLINE" > "MESSAGE" 字典序
};
sort(events.begin(),events.end(),cmp);
for(auto& e:events){
int curr_t=stoi(e[1]); // 当前时间
string& mention=e[2];
if(e[0][0]=='O'){ //离线事件
online_t[stoi(mention)]=curr_t+60; // 下次在线时间
}
//消息事件
else if(mention[0]=='A'){ // @所有人
for(int i=0;i<numberOfUsers;i++) ans[i]++;
}
else if(mention[0]=='H'){ // @所有在线用户
for(int i=0;i<numberOfUsers;i++){
if(curr_t>=online_t[i]) ans[i]++;
}
}
else{ // @id
int idx=0;
for(int i=0;i<mention.size();i++){
if(isdigit(mention[i])) idx=idx*10+(mention[i]-'0');
if(i+1==mention.size() || mention[i+1]==' '){
ans[idx]++;
idx=0;
}
}
}
}return ans; }};