带修改,询问区间内出现次数大于区间长度一半的数个数,N,Q<=500000
如果一个数在一个区间内出现次数大于一半,那么在区间内随机抽一些数,抽到这个数的个数通常会很多,因此可以用平衡树维护每个权值的出现位置,只查询在抽查中出现次数充分多的数
具体的,最坏情况下一个数在区间内出现次数为1/2区间长度,此时抽取100个数,这个数的出现次数<=25的概率为$10^-7$数量级,可以作为判定标准
#include<bits/stdc++.h> const int RN=100000; char buf[RN],*ptr=buf+RN,ob[RN],*op=ob; int G(){ if(ptr-buf==RN)fread(ptr=buf,1,RN,stdin); return *ptr++; } int _(){ int x=0; if(ptr<buf+RN-100){ while(*ptr<48)++ptr; while(*ptr>47)x=x*10+*ptr++-48; }else{ int c=G(); while(c<48)c=G(); while(c>47)x=x*10+c-48,c=G(); } return x; } #define fl fwrite(ob,1,op-ob,stdout),op=ob void pr(int x){ if(op>ob+RN-100)fl; if(x<0)x=-x,*op++='-'; int ss[15],sp=0; do ss[++sp]=x%10;while(x/=10); while(sp)*op++=ss[sp--]+48; *op++=10; } const int N=500007; int n,m,a[N]; struct node{ node*c[2]; int rnd,sz; void sp(node*x,node*&l,node*&r); }ns[N],*rt[N]; void node::sp(node*x,node*&l,node*&r){ if(this==ns){l=r=ns;return;} if(x<this){ r=this; c[0]->sp(x,l,c[0]); sz-=l->sz; }else{ l=this; c[1]->sp(x,c[1],r); sz-=r->sz; } } node*mg(node*a,node*b){ if(a==ns)return b; if(b==ns)return a; if(a->rnd>b->rnd){ a->sz+=b->sz; a->c[1]=mg(a->c[1],b); return a; } b->sz+=a->sz; b->c[0]=mg(a,b->c[0]); return b; } #define _w (*w) void ins(node**w,node*x){ while(x->rnd<_w->rnd)++_w->sz,w=_w->c+(_w<x); x->sz=1+_w->sz; _w->sp(x,x->c[0],x->c[1]); _w=x; } void del(node**w,node*x){ while(_w!=x)--_w->sz,w=_w->c+(_w<x); x->sz=1; _w=mg(x->c[0],x->c[1]); x->c[0]=x->c[1]=ns; } #undef _w int seed=0; int rnd(){ return seed=(seed*141+29399)%13999133; } int leq(int p,node*x){ int s=0; for(node*a=rt[p];a!=ns;){ if(a<=x)s+=a->c[0]->sz+1,a=a->c[1]; else a=a->c[0]; } return s; } int ts[N],tk=0,xs[N],xp; int query(int L,int R,int v){ ++tk; xp=0; for(int t=0;t<60;++t){ int pos=L+rnd()%(R-L+1); int x=a[pos]; if(!ts[x])xs[xp++]=x; ++ts[x]; if(++pos>R)pos=L; } for(int i=0;i<xp;++i)if(ts[xs[i]]>10){ int s=leq(xs[i],ns+R)-leq(xs[i],ns+L-1); if(s*2>R-L+1){ v=xs[i]; break; } } for(int i=0;i<xp;++i)ts[xs[i]]=0; return v; } int main(){ n=_(),m=_(); seed=n+m+1231^234; for(int i=1;i<=n;++i)rt[i]=ns; ns[0]=(node){ns,ns,-1,0}; for(int i=1;i<=n;++i){ ns[i]=(node){ns,ns,rnd(),1}; a[i]=_(); ins(rt+a[i],ns+i); } for(int i=1;i<=m;++i){ int l=_(),r=_(),s=_(),k=_(),ans=query(l,r,s); for(int j=0,x;j<k;++j){ x=_(); if(a[x]!=ans){ del(rt+a[x],ns+x); a[x]=ans; ins(rt+a[x],ns+x); } } pr(ans); } pr(query(1,n,-1)); return fl,0; }