问一下为什么块长不同会在WA和AC之间反复横跳?
查看原帖
问一下为什么块长不同会在WA和AC之间反复横跳?
320449
forest114514楼主2024/8/20 11:36

rt,我在写这个题的时候如果值域分块的块长开 800800 就能 AC,但是其他的很多块长比如 320,700,750,850320,700,750,850 我试了都会 WA 掉,有没有大佬帮蒟蒻解答一下这是为什么?

代码:(值域分块块长是 CC)

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;
}
2024/8/20 11:36
加载中...