Codeforces Round #366 (Div. 2) C. Thor

题意:

手机里有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;
}
View Code

 

posted @ 2016-08-09 20:11  fukan  阅读(266)  评论(0编辑  收藏  举报