1. 程式人生 > >【打CF,學演算法——三星級】Codeforces 704A Thor (模擬)

【打CF,學演算法——三星級】Codeforces 704A Thor (模擬)

題面:

A. Thor time limit per test 2 seconds memory limit per test 256 megabytes input standard input output standard output

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
Note

In the first sample:

  1. Application 3 generates a notification (there is 1 unread notification).
  2. Application 1 generates a notification (there are 2 unread notifications).
  3. Application 2 generates a notification (there are 3 unread notifications).
  4. Thor reads the notification generated by application 3, there are 2 unread notifications left.

In the second sample test:

  1. Application 2 generates a notification (there is 1 unread notification).
  2. Application 4 generates a notification (there are 2 unread notifications).
  3. Application 2 generates a notification (there are 3 unread notifications).
  4. Thor reads first three notifications and since there are only three of them so far, there will be no unread notification left.
  5. Application 3 generates a notification (there is 1 unread notification).
  6. Application 3 generates a notification (there are 2 unread notifications).

題意:

    此題背景是手機app產生未讀訊息,有n款app,對應三種事件,事件一,x號app產生一條新的未讀訊息。事件二,雷神讀了x號app的所有未讀資訊。事件三,雷神讀了最開始的t條訊息,(這些就是按順序產生的app訊息,不管讀沒讀)。每次事件後,都要輸出當前的未讀訊息數。

解題:

   解法中,資料結構採用一個訊息列表,記錄訊息,一個數量陣列,對應每個app未讀訊息數,一個訊息向量陣列,對應每個app產生的訊息記錄的下標,一個pos陣列,記錄每個app當前已經處理過最後一條資訊的後一個位置,一個sum值記錄總未讀訊息數,一個p值記錄時間順序上通過操作三當前處理過的最後一條訊息位置。

    對應操作一,可以設計一個訊息列表,每產生一條新的訊息,記錄該訊息的產生app編號,以及一個標誌代表該條訊息是否已讀,同時給該app對應的數量陣列數量加一,該款app的向量陣列記錄該條訊息下標,未讀訊息總數加一。

    對應操作二,可以從該款app的pos陣列中獲取到該款app最後處理的一條未讀資訊的後一個位置,並開始往後掃描讀,標記該條訊息為已讀。同時,總未讀訊息數減去該app對應未讀訊息數,並將該app未讀訊息數清零,更新最後處理未讀訊息的後一個位置資訊。

    對應操作三,只要從p(當前處理過最後一個位置開始處理即可),這個過程中會遇到未讀和已讀訊息,已讀的直接跳過,未讀的需要標記已讀,同時總sum值(未讀訊息數)減一,對應的該訊息產生app的未讀數量陣列的值也要減一。

   總的複雜度是O(n),因為每條訊息最多隻會產生一遍,讀一遍。

程式碼:

#include <iostream>
#include <vector>
#include <cstdio>
#include <cstring>
#define LL long long
#define sz 300010
using namespace std;
struct info
{
	int id;
	bool vis;
}store[sz];
int amount[sz];
int pos[sz];
vector <int> v[sz];
int main()
{
    int sum=0,n,q,a,b,p=0,cnt=0;
    scanf("%d%d",&n,&q);
    for(int i=0;i<q;i++)
    {
    	scanf("%d%d",&a,&b);
    	if(a==1)
    	{
	    	v[b].push_back(cnt);
	    	amount[b]++;
	    	sum++;
	    	store[cnt].vis=0;
	    	store[cnt].id=b;
	    	cnt++;
	    }
	    if(a==2)
	    {
    		sum-=amount[b];
    		amount[b]=0;
    		for(int j=pos[b];j<v[b].size();j++)
    		{
		    	store[v[b][j]].vis=1;
		    }
		    pos[b]=v[b].size();
    	}
    	if(a==3)
    	{
	    	for(int j=p;j<b;j++)
	    	{
	    		if(!store[j].vis)
	    		{
		    		store[j].vis=1;
		    		sum--;
		    		amount[store[j].id]--;
		    	}
	    	}
	    	p=max(p,b);
	    }
	    printf("%d\n",sum);
    }
	return 0;
}