题目链接:cf 704A
这个题是一个很好的题,首先理解题意就比较费劲,然后看上去是一个模拟的题,是需要用数据结构来维护的,暴力写是超时的
分析题意:
题目中给定了三种操作
操作1:第x种应用增加一个未读消息
操作2:我把第x种应用的消息全部读完(标记为已读)
操作3:我把所有的应用的消息按照时间从先到后的顺序,读取x个
在读取的时候,是可能会有重复读取的。
n=1e5,q=1e5
然后,每个操作之后,我们需要输出的是,在每个操作之后,当前的消息库中总共还有多少个未读消息
学到了一个线段树来维护未读消息的姿势!
竟然这样写没有超时,我很诧异
首先,搞两个数组来标记,当前的第几个应用的第几个消息是什么(因为是vector的push_back(),所以会是按照时间顺序的)
这个标记为vector<int> dui【maxn】
然后,我们还需要一个对全局都进行记录的vector<int> his
然后,很有意思的方法来了
对于操作1:我们使用线段树来维护
就有update函数,让x这个位置的值加1就好
然后his和dui【t】中都标记好当前的值就好
对于操作2:我们用另外一个update来搞
把这个x的位置上的值全部清0
然后,his中的所有值标为-1(表示读过了)
然后dui【x】的值清空(已经全部读过了)
对于操作3:如果当前需要判断的值x不超过当期的最大插入数量,那么直接输出线段树的根节点
否则,我们需要进行修改
强调一下容易理解错的几行代码
his.push_back(-1);
int Max=1;
这两行代码,是为了防止直接查询3的时候出错用的(在里面放了个无用数据)
下面贴代码:
#include<bits/stdc++.h>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
const int maxn=3e5+500;
int sum[maxn<<2];
vector<int> dui[maxn];
vector<int> his;
void PushUp(int rt){
sum[rt]=sum[rt<<1]+sum[rt<<1|1];
}
void Build(int l,int r,int rt){
if (l==r){
sum[rt]=0;
return;
}
int m=(l+r)>>1;
Build(lson);
Build(rson);
PushUp(rt);
}
void Update(int p,int x,int l,int r,int rt){
if (l==r){
sum[rt]=x;
return;
}
int m=(l+r)>>1;
if (p<=m) Update(p,x,lson);
else Update(p,x,rson);
PushUp(rt);
}
void Update1(int p,int x,int l,int r,int rt){
if (l==r){
sum[rt]+=x;
return;
}
int m=(l+r)>>1;
if (p<=m) Update1(p,x,lson);
else Update1(p,x,rson);
PushUp(rt);
}
int queryhe(int L,int R,int l,int r,int rt){
if (L<=l&&R>=r) return sum[rt];
int m=(l+r)>>1;
int ret=0;
if (L<=m) ret+=queryhe(L,R,lson);
if (R>m) ret+=queryhe(L,R,rson);
return ret;
}
int main(){
//freopen("input.txt","r",stdin);
int n,q;
while(scanf("%d%d",&n,&q)!=EOF){
memset(sum,0,sizeof(sum));
for(int i=0;i<maxn;i++) dui[i].clear();
his.clear();
his.push_back(-1);
Build(1,n,1);
int Max=1,total=0,op,t;
for(int i=1;i<=q;i++){
scanf("%d%d",&op,&t);
if (op==1){
total++;
Update1(t,1,1,n,1);
cout<<queryhe(1,n,1,n,1)<<endl;
his.push_back(t);
dui[t].push_back(total);
}
else if (op==2){
Update(t,0,1,n,1);
cout<<queryhe(1,n,1,n,1)<<endl;
int len=(int)dui[t].size();
for(int j=0;j<len;j++) his[dui[t][j]]=-1;
dui[t].clear();
}
else{
if (t<Max){
cout<<queryhe(1,n,1,n,1)<<endl;
}
else{
for(int j=Max;j<=t;j++){
int cur=his[j];
if (cur==-1) continue;
Update1(cur,-1,1,n,1);
his[j]=-1;
}
Max=t+1;
cout<<queryhe(1,n,1,n,1)<<endl;
}
}
}
}
return 0;
}