CF #366 DIV2 C. Thor 模拟 queue/stack降低复杂度

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 are napplications 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 tevents 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).

题意:给你n个邮箱,q个操作,1,y代表往y号邮箱塞一份信,2,y代表将y号邮箱内的信全部读完,

3,y代表将所有接收到的信(不管有没有读过)的前y封都读了,要求在每个操作之后输出未读的信数量;

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <map>
#include <vector>
#include <queue>
#include <cstring>
#include <string>
#include <algorithm>
using namespace std;
typedef  long long  ll;
typedef unsigned long long ull;
#define MM(a,b) memset(a,b,sizeof(a));
#define inf 0x7f7f7f7f
#define FOR(i,n) for(int i=1;i<=n;i++)
#define CT continue;
#define PF printf
#define SC scanf
const int mod=1000000007;
const int N=3*1e5+10;

queue<int> q;
int num[N],read[N],cnt[N];
int main()
{
    int n,k,x,y;
    while(~scanf("%d%d",&n,&k))
    {
       while(q.size()) q.pop();
       MM(num,0);MM(read,0);MM(cnt,0);
       int t=0,ans=0;

       for(int i=1;i<=k;i++)
       {
           scanf("%d%d",&x,&y);
           if(x==1)
            {
               num[y]++;
               ans++;
               q.push(y);
            }
           else if(x==2)
            {
               ans-=num[y]-read[y];
               read[y]=num[y];
            }
           else if(x==3)
            {
               while(t<y)
               {
                   t++;
                   int u=q.front();q.pop();
                   cnt[u]++;
                   if(cnt[u]>read[u])
                   {
                      read[u]++;
                      ans--;
                   }
               }
            }
            printf("%d
",ans);
       }
    }
    return 0;
}

  比赛分析:看到操作数是*1e5,又感觉是区间操作与询问,,首先就想到了线段树,然而却无法维护

3,y也就是读掉前y封信,这个操作,因为如果再开个数组维护前y封信的邮箱下标的话,复杂度肯定又上去了。。。

分析:其实只要模拟一遍就好,对于第三个操作,设置一个queue,记录顺序,最后最坏情况下每封信都

会进队一次,出队一次,再考虑q个操作,复杂度为q+n;

stack降低复杂度,主要是用于元素之间存在单调性;

queue降低复杂度,主要是用于元素只需遍历一次,不需要多次使用

原文地址:https://www.cnblogs.com/smilesundream/p/5748911.html