1. 程式人生 > >Codeforces Round #366 (Div. 2) C. Thor

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

題目連結:點選開啟連結
C. 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 aren 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 firstt
    events of the first type). It's guaranteed that there were at leastt events of the first type before this event. Please note that he doesn't read firstt unread notifications, he just reads the very firstt 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 andq (1 ≤ n, q ≤ 300 000) — the number of applications and the number of events to happen.

The next q lines contain the events. Thei-th of these lines starts with an integertypei — type of thei-th event. If typei = 1 ortypei = 2 then it is followed by an integerxi. Otherwise it is followed by an integerti (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是運算元量 (n,q<=300000)

給你三種操作:

1 x:表示第x個應用發出一條推送。

2 x:表示讀完第x個應用發出的所有推送(有可能重複讀一條推送)。

3 x:表示讀完前x條推送(也有可能重複讀一條推送)。

每進行一次操作,問當前未讀的推送;


思路:暴力的複雜度有O(n*q),

           容易看出,對於第二種操作,只要開一個數組記錄第x個應用已經讀的推送個數,再對比這個應用所有推送個數就能得到答案。但是由於第三種操作的存在,多了一種讀取推送的方式,上述方法錯誤。

           但我們可以肯定當前第二種操作讀取的推送個數(q)肯定不需要考慮第x個應用之前第二種操作已經讀取的推送個數(w),那麼再考慮在w+1到q之間的推送是否已經被第三種操作讀取過,那麼問題轉到第三種操作上,同理第三種操作也是考慮現在的x與之前第三種操作額最大值y的比較,如果x>y那麼就要考慮在y+1到x之前的推送受到第二種操作的影響。所以只要開一個vis陣列,記錄是否當前推送被訪問就可以了。但是無論如何,對於每種操作所有推送只會被訪問一遍,所以就是o(n)的時間。

程式碼:

#include <bits/stdc++.h>

using namespace std;
const int N=300005;
int head[N];
bool vis[N];
int n,cnt;
struct Edge
{
    int next,v;
};
Edge edge[N];
void add(int u,int v)
{
    edge[cnt].next=head[u];
    edge[cnt].v=v;
    head[u]=cnt++;
}
int main()
{
    int q,a,b,number=0,use=0,prelen=0,flag,cnt=0;
    memset(head,-1,sizeof(head));
    scanf("%d %d",&n,&q);
    for(int i=1;i<=q;i++)
    {
        scanf("%d%d",&a,&b);
        if(a==1)
        {
            number++;
            add(b,number);
            printf("%d\n",number-use);
            continue;
        }
        if(a==2)
        {
            for(int j=head[b];j!=-1;j=edge[j].next)
            {
                flag=edge[j].v;
                if(!vis[flag])
                {
                    use++;
                    vis[flag]=true;
                }
            }
            head[b]=-1;                //清除之前所有存在的對於b這個應用的推送 即 消除之前所有邊
            printf("%d\n",number-use);
            continue;
        }
        for(int j=prelen+1;j<=b;j++)
        {
            if(!vis[j])
            {
                use++;
                vis[j]=true;
            }
        }
        prelen=max(prelen,b);       // 取第三種操作的最大值
        printf("%d\n",number-use);
    }
    return 0;
}