rt,我在写这个题的时候如果值域分块的块长开 800 就能 AC,但是其他的很多块长比如 320,700,750,850 我试了都会 WA 掉,有没有大佬帮蒟蒻解答一下这是为什么?
代码:(值域分块块长是 C)
const int N=1e5+100,C=800,B=450,V=1e5,S=N/B+10;
int n,m,c[N],L[S],R[S],bl,pos[N];
int hd[S][N],fa[N],upd;
int sum[S][N],tag[S][V/C+10],fr[N],tot;
il int getf(int x){return fa[x]==x?x:fa[x]=getf(fa[x]);}
void init(){
bl=n/B;
rep(i,1,bl){
L[i]=R[i-1]+1,R[i]=L[i]+B-1;
rep(j,L[i],R[i]) pos[j]=i;
}
if(R[bl]<n){
++bl;
L[bl]=R[bl-1]+1,R[bl]=n;
rep(j,L[bl],R[bl]) pos[j]=bl;
}
tot=V/C;
for(int i=1,l=1;i<=tot;++i,l+=C) rep(j,l,l+C-1) fr[j]=i;
if(tot*C<V){++tot;rep(j,tot*C+1,V) fr[j]=tot;}
rep(p,1,bl){
rep(i,1,V) sum[p][i]=sum[p-1][i];
rep(i,1,tot) tag[p][i]=tag[p-1][i];
rep(i,L[p],R[p]){
fa[i]=(hd[p][c[i]]?hd[p][c[i]]:(hd[p][c[i]]=i));
++sum[p][c[i]],++tag[p][fr[c[i]]];
}
}
}
void rebuild(int p,int l,int r,int x,int y){
rep(i,L[p],R[p]) c[i]=c[getf(i)];
rep(i,l,r) if(c[i]==x) c[i]=y,++upd;
hd[p][x]=hd[p][y]=0;
rep(i,L[p],R[p]) if(c[i]==x||c[i]==y) fa[i]=(hd[p][c[i]]?hd[p][c[i]]:(hd[p][c[i]]=i));
sum[p][x]-=upd,sum[p][y]+=upd;
tag[p][fr[x]]-=upd,tag[p][fr[y]]+=upd;
}
void update(int p,int x,int y){
upd+=sum[p][x]-(sum[p-1][x]+upd);
sum[p][x]-=upd,sum[p][y]+=upd;
tag[p][fr[x]]-=upd,tag[p][fr[y]]+=upd;
//我是 shaber
if(!hd[p][x]) return;
if(!hd[p][y]){
c[hd[p][x]]=y;
hd[p][y]=hd[p][x],hd[p][x]=0;
return;
}
rep(i,L[p],R[p]) c[i]=c[getf(i)];
rep(i,L[p],R[p]) if(c[i]==x) c[i]=y;
fa[hd[p][x]]=hd[p][y],hd[p][x]=0;
}
void modify(int l,int r,int x,int y){//修改
if(x==y) return;//无语了。
int pl=pos[l],pr=pos[r];
upd=0;
if(pl==pr){
rebuild(pl,l,r,x,y);
rep(p,pr+1,bl) sum[p][x]-=upd,sum[p][y]+=upd,tag[p][fr[x]]-=upd,tag[p][fr[y]]+=upd;
return;
}
rebuild(pl,l,R[pl],x,y);
rep(p,pl+1,pr-1) update(p,x,y);
rebuild(pr,L[pr],r,x,y);
rep(p,pr+1,bl) sum[p][x]-=upd,sum[p][y]+=upd,tag[p][fr[x]]-=upd,tag[p][fr[y]]+=upd;
}
int query(int l,int r,int k){
int pl=pos[l],pr=pos[r];
if(pl==pr){
rep(i,l,r) c[i]=c[getf(i)],sum[bl+1][c[i]]++,tag[bl+1][fr[c[i]]]++;
rep(p,1,tot){
if(k>tag[bl+1][p]) k-=tag[bl+1][p];
else{
int lim=min(p*C,V);
rep(i,(p-1)*C+1,lim) {
if(k>sum[bl+1][i]) k-=sum[bl+1][i];
else{
rep(j,l,r) sum[bl+1][c[j]]--,tag[bl+1][fr[c[j]]]--;
return i;
}
}
}
}
assert(0);
}
rep(i,l,R[pl]) c[i]=c[getf(i)],sum[bl+1][c[i]]++,tag[bl+1][fr[c[i]]]++;
rep(i,L[pr],r) c[i]=c[getf(i)],sum[bl+1][c[i]]++,tag[bl+1][fr[c[i]]]++;
rep(p,1,tot){
if(k>tag[pr-1][p]-tag[pl][p]+tag[bl+1][p]) k-=tag[pr-1][p]-tag[pl][p]+tag[bl+1][p];
else{
int lim=min(p*C,V);
rep(i,(p-1)*C+1,lim) {
if(k>sum[pr-1][i]-sum[pl][i]+sum[bl+1][i]) k-=sum[pr-1][i]-sum[pl][i]+sum[bl+1][i];
else{
rep(j,l,R[pl]) sum[bl+1][c[j]]--,tag[bl+1][fr[c[j]]]--;
rep(j,L[pr],r) sum[bl+1][c[j]]--,tag[bl+1][fr[c[j]]]--;
return i;
}
}
}
}
// assert(0);
return -1;
}
bool _ED;
signed main(){
// fprintf(stderr,"%.20lf MB\n",(&_ST-&_ED)/1048576.0);
//ios::sync_with_stdio(false);
//cin.tie(0);cout.tie(0);
// freopen("data.in","r",stdin);
// freopen("mine.out","w",stdout);
read(n,m);
rep(i,1,n) read(c[i]);
init();
rep(i,1,m){
int op,l,r;read(op,l,r);
if(op==1){
int x,y;read(x,y);
modify(l,r,x,y);
}
else{
int k;read(k);
write(query(l,r,k),'\n');
}
}
return 0;
}