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

题意:

手机上有n个程序,接下来有q个事件,事件类型分为三种:

1.程序x生成一个新消息

2.阅读程序x的所有消息

3.阅读前x个事件类型为1的事件包含的一个消息

对于每次事件后问所有程序有几条消息没有阅读,一开始所有程序都没有消息。


题解:

模拟。ans表示当前有几条消息未读,num[i]表示当前程序i总共有几条消息,read[i]表示程序i已阅读的消息数,last[i][0]表示第i个程序最后一条消息的序号,last[i][1]表示第i个程序最后一条已阅读的消息的序号,maxn表示前maxn条消息已阅读,队列que保存事件类型1的序号以及程序序号。

对于事件类型1可以将它包含的程序序号以及序号保存到队列中然后直接输出++ans,并更新num[x]与last[x][0]

对于事件类型2可以直接输出ans -= num[x]-read[x],并更新last[x][1]和read[x]

对于事件类型3可以将前x-maxn个元素出队,last[i][1]进行判断之前有无阅读过


#include<iostream>
#include <stdio.h>
#include <algorithm>
#include <math.h>
#include<stdlib.h>
#include <string.h>
#include<queue>
#include<set>
#include<map>
#include<stack>
#include<time.h>
using namespace std;
#define MAX_N 300005
#define inf 0x7fffffff
#define LL long long
#define ull unsigned long long
#define mod 10007
LL INF=9e18;

struct node
{
    int n, k;
    node(int _n, int _k) {n=_n;k=_k;};
};
int num[MAX_N];
int read[MAX_N];
int last[MAX_N][2];
int total=0;
int maxn = 0;
queue<node>que;
int main()
{
    int n, q;
    cin >> n >> q;
    memset(num, 0, sizeof(num));
    memset(read, 0, sizeof(read));
    memset(last, 0, sizeof(last));
    int ans = 0;
    for(int k=0;k<q;k++) {
        int t, x;
        cin >> t >> x;
        if(t == 1) {
            que.push(node(++total, x));
            num[x]++;
            last[x][0] = total;
            ans++;
        }
        else if(t == 2) {
            last[x][1] = last[x][0];
            ans -= (num[x] - read[x]);
            read[x] = num[x];
        }
        else {
            int tmp = x - maxn;
            for(int i=0;i<tmp&&!que.empty();i++) {
                node n = que.front();
                que.pop();
                maxn++;
                if(last[n.k][1] < n.n) {
                    ans--;
                    last[n.k][1] = n.n;
                    read[n.k]++;
                }
            }
        }
        cout << ans << endl;
    }
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值