CF940F Machine Learning(带修莫队)
Posted hfctf0210
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CF940F Machine Learning(带修莫队)相关的知识,希望对你有一定的参考价值。
首先显然应该把数组离散化,然后发现是个带修莫队裸题,但是求mex比较讨厌,怎么办?其实可以这样求:记录每个数出现的次数,以及出现次数的出现次数。至于求mex,直接暴力扫最小的出现次数的出现次数为0的正整数,就一句话,这样看似会超时,实际上是O(√n)的复杂度。为什么?假设存在出现1,2,...,x的出现次数,则Σi(1<=i<=x)<=n,即x*(x+1)<=2*n,所以x至多是√n级别。很多人再把出现次数分块,根本没必要。然后考虑把数组分块的块大小,每次移动左指针,为O(n*块大小),移动右指针,为O(n*块大小+n*块个数),移动修改标记,为O(n*块个数2),然后显然块大小为O(n2/3)最优,复杂度O(n5/3)
#include<bits/stdc++.h> using namespace std; const int N=2e5+7; struct queryint l,r,t,id;q[N]; struct mdfint pos,pre,now;d[N]; int n,m,B,l=1,r,cnt,qcnt,mcnt,a[N],b[N],c[N],tmp[N],tot[N],num[N],ans[N]; bool cmp(query a,query b) if((a.l-1)/B!=(b.l-1)/B)return a.l<b.l; return(a.r-1)/B==(b.r-1)/B?a.t<b.t:a.r<b.r; void add(int x,int v)tot[num[x]]--,num[x]+=v,tot[num[x]]++; void modify(int i,int f) if(d[i].pos>=l&&d[i].pos<=r)add(a[d[i].pos],-1); a[d[i].pos]=f==1?d[i].now:d[i].pre; if(d[i].pos>=l&&d[i].pos<=r)add(a[d[i].pos],1); int main() scanf("%d%d",&n,&m); for(int i=1;i<=n;i++)scanf("%d",&a[i]),tmp[++cnt]=a[i]; for(int i=1;i<=m;i++) int op,x,y;scanf("%d%d%d",&op,&x,&y); if(op==1)q[++qcnt]=(query)x,y,mcnt,qcnt; else d[++mcnt]=(mdf)x,0,y,tmp[++cnt]=y; sort(tmp+1,tmp+cnt+1); cnt=unique(tmp+1,tmp+cnt+1)-tmp-1; for(int i=1;i<=n;i++)a[i]=b[i]=lower_bound(tmp+1,tmp+cnt+1,a[i])-tmp; for(int i=1;i<=mcnt;i++) d[i].now=lower_bound(tmp+1,tmp+cnt+1,d[i].now)-tmp; d[i].pre=b[d[i].pos],b[d[i].pos]=d[i].now; B=pow(n,0.67); sort(q+1,q+qcnt+1,cmp); for(int i=1,tm=0;i<=qcnt;i++) while(tm<q[i].t)modify(++tm,1); while(tm>q[i].t)modify(tm--,-1); while(r<q[i].r)add(a[++r],1); while(l>q[i].l)add(a[--l],1); while(r>q[i].r)add(a[r--],-1); while(l<q[i].l)add(a[l++],-1); ans[q[i].id]=1; while(tot[ans[q[i].id]])ans[q[i].id]++; for(int i=1;i<=qcnt;i++)printf("%d\n",ans[i]);
以上是关于CF940F Machine Learning(带修莫队)的主要内容,如果未能解决你的问题,请参考以下文章