CF 704A Thor
2016-08-18 22:26
211 查看
description
这道题是说一共有m个操作(M<=100000),操作分为3种,对于第一种操作,在队列末尾加入一个正整数x(X<=100000),对于操作二,将队列中权值为x的值全部标为0,但并不踢出队列,对于操作三,将队列的前i个全部标为0。也就是说,一个点有可能被重复标为0。对于每个操作,求操作后剩余多少个不为0的数。
Solution
一开始就想到了线段树,但后来才发现其实是不需要的,只感觉自己蠢了。。。
对于操作1,我们在一个桶中在x的位置上加1,并给答案加1,并在队列中加入这个数,尾指针右移。
而对于操作二,我们直接将答案减去桶中x位置上的值,并将这个值清空,将对x最新的一次操作定为现在队列的尾指针即可。
对于操作三,我们将头指针到i的数逐个判断,看它最新的一次操作是否大于它自己的位置,假如不是就将它减去,并更新桶的值和答案,将头指针与i取个较大值赋为头指针的新值。
Tips:看起来这样做一次操作是O(N)的,实则不然。对于队列里的每个数,我只要查过一次以后就再也不会再次查询,关键就在于对于每次操作三后头指针与i取个较大值作为头指针的新值,所以整个的复杂度是O(N)的。
代码
#include<iostream> #include<cmath> #include<cstring> #include<cstdio> #include<algorithm> using namespace std; const int maxn=300005; int f[maxn],d[maxn],b[maxn],c[maxn],a[maxn],n,m,i,t,j,k,l,x,y,tot,ans; int main(){ // freopen("data.in","r",stdin);freopen("data.out","w",stdout); scanf("%d%d",&n,&m);tot=1; for (i=1;i<=m;i++){ scanf("%d%d",&x,&y); if (x==1) d[++d[0]]=y,c[y]=d[0],a[y]++,ans++; else if (x==2) b[y]=c[y],ans-=a[y],a[y]=0; else{ for (j=tot;j<=y;j++) if (b[d[j]]<j) a[d[j]]--,ans--,b[d[j]]=j; tot=max(tot,y+1); } printf("%d\n",ans); } }
相关文章推荐
- 【打CF,学算法——三星级】Codeforces 704A Thor (模拟)
- Codeforces-704A-Thor
- codeforces 704A Thor [技巧吧.]
- CodeForces 704A Thor
- Codeforces 704A Thor (脑洞题)
- 【CodeForces】704A - Thor(队列,详解)
- 【codeforces 704A Thor】
- Thor(CF #366 Div. 1)
- cf-114A
- cf 546C Soldier and Cards
- CF 548A
- CF 303C——Minimum Modular——————【剪枝】
- 素数打表 cf 546D
- CF 1B Spreadsheet
- CF 9B Running Student
- CF 11B Jumping Jack
- iOS之CF和OC之间类型转换
- CF 3B Lorry
- cf NEERC 14 J - Jokewithpermutation
- 【分块】 CF 551 E GukiZ and GukiZiana