题意:
手机里有n个应用,有三类操作。
第一类,第x个应用产生一个提醒通知
第二类,阅读了第x个应用产生的所有提醒通知,可能重复阅读已经读过的。
第三类,阅读了从头开始产生的t个提醒通知,可能重复阅读已经读过的。
输出每个操作发生后未读消息的个数。
分析:
对产生的消息进行编号,编号唯一。
未读的消息构成一个上述产生消息的子集s。
每个消息属于特定的应用,每个应用产生的消息构成队列。
这样,
1操作同时维护应用x产生的队列和整个的消息集合。
2操作读取应用x的消息队列,然后删除集合s中的这些消息。
3操作删除集合s中的前t个消息,此题不需要在这类操作中维护删除的前t个消息属于哪一类。
有一个优化就是,为了避免重复而无意义的erase操作,每次都要记录最大的起点last,已经删除
的消息就不需要重复操作了。
使用集合的好处是 可以指定删除哪个元素不是以索引而是以“内容”。
#include<cstdio> #include<algorithm> #include<map> #include<cstring> #include<string> #include<iostream> #include<set> #include<vector> using namespace std; typedef long long ll; const int mod = 1000000000+7; const int maxn = 300010; vector<int> app[maxn]; set<int> cnt; int main() { int n,q,x,type,num; while(~scanf("%d%d",&n,&q)) { num = 0; cnt.clear(); int last = 0; for(int i=0;i<q;i++) { scanf("%d%d",&type,&x); if(type==1) { app[x].push_back(++num); cnt.insert(num); } else if(type==2) { for(int i=0;i<app[x].size();i++) cnt.erase(app[x][i]); app[x].clear(); } else { for(int i=last;i<=x;i++) { cnt.erase(i); } last = max(x,last); } printf("%d\n",cnt.size()); } } return 0; }
时间: 2024-12-15 01:57:57