CF643G Choosing Ads

Link
(k=lfloorfrac{100}p floor),那么查询就是求(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