传送门
区间绝对众数的线性做法拓展成区间合并,懒得写题解了。
代码:
#include<bits/stdc++.h>
#define ll long long
#define re register
#define cs const
namespace IO{
inline char gc(){
static cs int Rlen=1<<22|1;
static char buf[Rlen],*p1,*p2;
return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,Rlen,stdin),p1==p2)?EOF:*p1++;
}
template<typename T>
inline T get(){
char c;T num;
while(!isdigit(c=gc()));num=c^48;
while(isdigit(c=gc()))num=(num+(num<<2)<<1)+(c^48);
return num;
}
inline int gi(){return get<int>();}
}
using namespace IO;
using std::cerr;
using std::cout;
cs int N=1.5e5+7;
int p;
struct node{int cnt,a[5],b[5];}t[N<<2],tp;
int tag[N<<2];
inline node operator+(cs node &x,cs node &y){
node z=x;
for(int re i=0;i<y.cnt;++i){
bool flag=0;
for(int re j=0;j<z.cnt;++j)
if(z.a[j]==y.a[i]){z.b[j]+=y.b[i];flag=true;break;}
if(flag)continue;
if(z.cnt<p){
z.a[z.cnt]=y.a[i];
z.b[z.cnt++]=y.b[i];
continue;
}int k=0;
for(int re j=1;j<z.cnt;++j)if(z.b[j]<z.b[k])k=j;
if(y.b[i]<z.b[k])for(int re j=0;j<z.cnt;++j)z.b[j]-=y.b[i];
else {
int tp=z.b[k];
z.a[k]=y.a[i];z.b[k]=y.b[i];
for(int re j=0;j<z.cnt;++j)z.b[j]-=tp;
}
}
return z;
}
#define lc u<<1
#define rc u<<1|1
inline void pushdown(int u,int len){
int &x=tag[u];
if(x){
tag[lc]=tag[rc]=t[lc].a[0]=t[rc].a[0]=x;
t[lc].cnt=t[rc].cnt=1;x=0;
t[lc].b[0]=len+1>>1,t[rc].b[0]=len>>1;
}
}
int a[N];
inline void build(int u,int l,int r){
if(l==r){t[u].cnt=1,t[u].a[0]=a[l],t[u].b[0]=1;return ;}
int mid=l+r>>1;
build(lc,l,mid);build(rc,mid+1,r);
t[u]=t[lc]+t[rc];
}
inline void modify(int u,int l,int r,int ql,int qr,int v){
if(ql<=l&&r<=qr){
t[u].cnt=1,tag[u]=t[u].a[0]=v,t[u].b[0]=r-l+1;
return ;
}pushdown(u,r-l+1);
int mid=l+r>>1;
if(ql<=mid)modify(lc,l,mid,ql,qr,v);
if(mid<qr)modify(rc,mid+1,r,ql,qr,v);
t[u]=t[lc]+t[rc];
}
inline void query(int u,int l,int r,int ql,int qr){
if(ql<=l&&r<=qr){tp=tp+t[u];return ;}
int mid=l+r>>1;pushdown(u,r-l+1);
if(ql<=mid)query(lc,l,mid,ql,qr);
if(mid<qr)query(rc,mid+1,r,ql,qr);
}
int n,m;
signed main(){
#ifdef zxyoi
freopen("ad.in","r",stdin);
#endif
n=gi(),m=gi(),p=100/gi();
for(int re i=1;i<=n;++i)a[i]=gi();
build(1,1,n);
while(m--){
switch(gi()){
case 1:{
int l=gi(),r=gi(),v=gi();
modify(1,1,n,l,r,v);
break;
}
case 2:{
tp.cnt=0;
int l=gi(),r=gi();
query(1,1,n,l,r);cout<<tp.cnt;
for(int re i=0;i<tp.cnt;++i)cout<<" "<<tp.a[i];
cout<<"\n";
break;
}
}
}
return 0;
}