题目链接:http://codeforces.com/contest/705/problem/C
题意:
input
4 6 1 2 1 4 1 2 3 3 1 3 1 3
output
1 2 3 0 1 2
操作类型1:app x增加一条未读信息。
操作类型2:一次把app x的未读信息全部读完。
操作类型3:按照操作类型1添加的顺序,按顺序读t条信息,注意这t条信息可能有的已经读过。
问每次操作后剩多少条未读信息。
本来想用线段树搞,但是操作3怎么也想不出来怎么实现。后来发现模拟可以过,感觉这其中的逻辑不太好想,特别是操作2和操作3的关系,错了好几次之后终于过了。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int MAX_N = 300100;
//mes是把所有收到信息按顺序存入
//appms是指第i个app的所有信息数
//appr指第i个app的所有已读信息数
//read指操作3中第i个app读的信息数
int mes[MAX_N], appm[MAX_N], appr[MAX_N], read[MAX_N];
int main() {
int n, q, i, j;
scanf("%d %d", &n, &q);
//cnt指总信息数,last指操作3上一次读到了哪一条信息
//p是数组mes的一个指针
int cnt = 0, ans = 0, last = 0, p = 0;
for(i = 0; i < q; i++) {
int x, y;
scanf("%d %d", &x, &y);
if(x == 1) {
mes[cnt++] = y;
appm[y]++;
ans++;
}
else if(x == 2) {
ans -= appm[y] - appr[y]; //未读的就是全部的的减去已读的
appr[y] = appm[y];
}
else {
if(last < y) { //若大于等于则读不到未读信息
for(; p < y; p++) {
read[mes[p]]++;
if(read[mes[p]] > appr[mes[p]]) { //读到了未读信息
ans -= read[mes[p]] - appr[mes[p]];
appr[mes[p]] = read[mes[p]];
}
}
last = y;//更新last
}
}
printf("%d\n", ans);
}
return 0;
}