**
CodeForces 705C
**
Thor is getting used to the Earth. As a gift Loki gave him a smartphone. There are n applications on this phone. Thor is fascinated by this phone. He has only one minor issue: he can’t count the number of unread notifications generated by those applications (maybe Loki put a curse on it so he can’t).
q events are about to happen (in chronological order). They are of three types:
1.Application x generates a notification (this new notification is unread).
2.Thor reads all notifications generated so far by application x (he may re-read some notifications).
3.Thor reads the first t notifications generated by phone applications (notifications generated in first t events of the first type). It’s guaranteed that there were at least t events of the first type before this event. Please note that he doesn’t read first t unread notifications, he just reads the very first t notifications generated on his phone and he may re-read some of them in this operation.
Please help Thor and tell him the number of unread notifications after each event. You may assume that initially there are no notifications in the phone.
Input
The first line of input contains two integers n and q (1 ≤ n, q ≤ 300 000) — the number of applications and the number of events to happen.
The next q lines contain the events. The i-th of these lines starts with an integer typei — type of the i-th event. If typei = 1 or typei = 2 then it is followed by an integer xi. Otherwise it is followed by an integer ti (1 ≤ typei ≤ 3, 1 ≤ xi ≤ n, 1 ≤ ti ≤ q).
Output
Print the number of unread notifications after each event.
Examples
Input
3 4
1 3
1 1
1 2
2 3
Output
1
2
3
2
Input
4 6
1 2
1 4
1 2
3 3
1 3
1 3
Output
1
2
3
0
1
2
题意
大概就是说手机上有n个应用,q条通知,接下来有q行,每行两个数,t1 和 t2,当 t1=1或者 t1=2时,1<=t2<=n,否则,1<=t2<=q;当t1=1时,序号为 t2 的应用产生一条消息,当 t1=2时,序号为 t2 的应用消息全被查看,当 t1=3时,前 t2 条被查看,最后一条消息可被多次查看。
解题思路
原本的思路是开两个数组,一个存储每个应用产生的信息数,一个标记该应用的信息前多少条被查看,然后进行加减运算,感觉大体思路应该是对的,但是结果却一直wrong answer on test 4。
去搜了一下各路大神的解法,发现我的思路大方向是正确的,但是我读错了题,误以为情况三是每个应用的前t2条信息被查看…
不过正好学习一下大佬们的解法,找到了一份用队列遍历,set标记的代码,半天终于看懂了,不得不说方法是真的妙。
下面代码的大概意思就是给每个应用开一个队列,用set标记队列里添加了多少次元素,当x=2时,将set和队列里同时存在的元素从set里删除,同时对答案进行加减,当x=3时,将set从头遍历,删除小于t2的元素,同时对答案进行加减。
#include<stdio.h>
#include<string.h>
#include<queue>
#include<set>
using namespace std;
queue<int>qe[300007];
set<int>se;
int main()
{
int n,q,x,t;
int sum=0,cnt=0;
scanf("%d %d",&n,&q);
for(int i=1;i<=q;i++)
{
scanf("%d %d",&x,&t);
if(x==1)
{
qe[t].push(cnt);
se.insert(cnt++);
sum++;
}
else if(x==2)
{
while(!qe[t].empty())
{
int cd=qe[t].front();qe[t].pop();
if(se.count(cd)==1)
{
sum--;
se.erase(cd);
}
}
}
else if(x==3)
{
set<int>::iterator it;
for(it=se.begin();it!=se.end();)
{
if(*it<t)
{
se.erase(it++);
sum--;
}
else break;
}
}
printf("%d\n",sum);
}
return 0;
}