Link
设\(k=\lfloor\frac{100}p\rfloor\),那么查询就是求\(\frac 1k\)绝对众数。
因为只要保证输出包含所有\(\frac 1k\)绝对众数,所以线段树维护Moore投票法即可。
#include<cstdio> #include<cctype> const int N=150007; int read(){int x=0,c=getchar();while(isspace(c))c=getchar();while(isdigit(c))(x*=10)+=c&15,c=getchar();return x;} int n,m,p; struct node{int n,a[5],b[5];void out(){printf("%d ",n);for(int i=0;i<n;++i) printf("%d ",a[i]);puts("");}}t[N<<2]; node operator+(node a,node b) { node c=b; for(int i=0,f,j,k,t;i<a.n;++i) { for(f=j=0;j<c.n;++j) if(c.a[j]==a.a[i]) {c.b[j]+=a.b[i];f=1;break;} if(f) continue; if(c.n<p) {c.a[c.n]=a.a[i],c.b[c.n]=a.b[i],++c.n;continue;} for(k=0,j=1;j<p;++j) if(c.b[j]<c.b[k]) k=j; if(a.b[i]<c.b[k]) for(j=0;j<p;++j) c.b[j]-=a.b[i]; else for(t=c.b[k],c.a[k]=a.a[i],c.b[k]=a.b[i],j=0;j<p;++j) c.b[j]-=t; } return c; } int tag[N<<2],len[N<<2]; #define ls p<<1 #define rs p<<1|1 #define mid ((l+r)>>1) void pushup(int p){t[p]=t[ls]+t[rs];} void modify(int p,int x){tag[p]=x,t[p].n=1,t[p].a[0]=x,t[p].b[0]=len[p];} void pushdown(int p){if(tag[p])modify(ls,tag[p]),modify(rs,tag[p]),tag[p]=0;} void build(int p,int l,int r) { if(l==r) return len[p]=t[p].n=t[p].b[0]=1,t[p].a[0]=read(),void(); build(ls,l,mid),build(rs,mid+1,r),pushup(p),len[p]=len[ls]+len[rs]; } void update(int p,int l,int r,int L,int R,int x) { if(L>r||l>R) return ; if(L<=l&&r<=R) return modify(p,x); pushdown(p),update(ls,l,mid,L,R,x),update(rs,mid+1,r,L,R,x),pushup(p); } node query(int p,int l,int r,int L,int R) { if(L<=l&&r<=R) return t[p]; pushdown(p); if(R<=mid) return query(ls,l,mid,L,R); if(L>mid) return query(rs,mid+1,r,L,R); return query(ls,l,mid,L,R)+query(rs,mid+1,r,L,R); } #undef ls #undef rs int main() { n=read(),m=read(),p=100/read(),build(1,1,n); for(int l,r;m;--m) read()==1? (l=read(),r=read(),update(1,1,n,l,r,read())):(l=read(),r=read(),query(1,1,n,l,r).out()); }
来源:https://www.cnblogs.com/cjoierShiina-Mashiro/p/12425588.html