「LG5692-手牵手走向明天」题解
P5692 [MtOI2019] 手牵手走向明天
sol
基础部分
小清新分块题,脑抽调了一整天。
首先因为可以离线,且信息更新不难,为了减小常数,考虑逐块处理。
我们储存下每个颜色对应编号,可以方便进行修改处理。
由于修改部分的需要,我们考虑回收利用编号以确保空间正确性。
修改
对于整块修改,如果原先存在 \(y\),那么直接 \(O(B)\) 暴力重构,这样颜色会减小 \(1\),不会超过 \(n\) 次。
如果不存在 \(y\),直接 \(y=x,x=0\) 即可。
然后是散块修改,同样暴力重构即可。
查询
考虑将答案分为块内和块间,块内答案的维护是简单的,一个块内最多只有 \(B\) 种颜色,可以直接开桶 \(B^2\) 储存,每次暴力重构的时候重新计算即可。对于散块,每次遍历一遍算出来就行。
对于块间答案,我们只需要这一块之前的最后一个位置,与这一块的第一个出现位置来更新即可。整块维护这个信息,散块每次扫一遍算出来。然后更新最后一个位置。
code
const int N=1e5+5,B=320,M=B+10;
int n,m;
int idx;
int a[N],mp[N];
int fst[M],lst[M];
int top,st[M];
int ans[M][M];
struct query{int o,l,r,x,y,ans=inf,lstx=-inf,lsty=-inf;}qs[N];
inline void solve(int L,int R){
auto rebuild=[&](int x){
fst[x]=inf,lst[x]=-inf;
rep(i,L,R)if(a[i]==x)chmin(fst[x],i),chmax(lst[x],i);
memset(ans[x],0x3f,sizeof ans[x]);
rep(i,1,idx)ans[i][x]=inf;
if(lst[x]>0){
int d=inf;
rep(i,L,R){
if(a[i]==x)d=0;
else ++d;
chmin(ans[x][a[i]],d);
chmin(ans[a[i]][x],d);
}
d=inf;
per(i,R,L){
if(a[i]==x)d=0;
else ++d;
chmin(ans[x][a[i]],d);
chmin(ans[a[i]][x],d);
}
}
};
auto modify=[&](int l,int r,int &x,int &y){
if(!x||x==y)return;
if(l==L&&r==R){
if(!y)return swap(x,y);
rep(i,l,r)if(a[i]==x)a[i]=y;
rebuild(x);rebuild(y);
st[++top]=x,x=0;
}else{
if([&](){rep(i,l,r)if(a[i]==x)return 0;return 1;}())return;
if(!y)y=(top?st[top--]:++idx);
rep(i,l,r)if(a[i]==x)a[i]=y;
rebuild(x);rebuild(y);
if(lst[x]==-inf)st[++top]=x,x=0;
}
};
auto query=[&](int i,int l,int r,int &x,int &y){
if(!x&&!y)return;
if(l==L&&r==R){
if(x&&y)chmin(qs[i].ans,ans[x][y]);
if(x)chmin(qs[i].ans,fst[x]-qs[i].lsty);
if(y)chmin(qs[i].ans,fst[y]-qs[i].lstx);
if(x)qs[i].lstx=lst[x];
if(y)qs[i].lsty=lst[y];
}else{
int ans=inf;
int fstx=inf,lstx=-inf,fsty=inf,lsty=-inf;
rep(i,l,r){
if(a[i]==x)chmin(fstx,i),chmax(lstx,i);
if(a[i]==y)chmin(fsty,i),chmax(lsty,i);
}
int d=inf;
rep(i,l,r){
if(a[i]==x)d=0;
else ++d;
if(a[i]==y)chmin(ans,d);
}
d=inf;
per(i,r,l){
if(a[i]==x)d=0;
else ++d;
if(a[i]==y)chmin(ans,d);
}
chmin(qs[i].ans,ans);
if(lstx>0)chmin(qs[i].ans,fstx-qs[i].lsty);
if(lsty>0)chmin(qs[i].ans,fsty-qs[i].lstx);
if(lstx>0)qs[i].lstx=lstx;
if(lsty>0)qs[i].lsty=lsty;
}
};
idx=top=0;
rep(i,1,1e5)mp[i]=0;
rep(i,L,R)a[i]=(mp[a[i]]?mp[a[i]]:mp[a[i]]=++idx);
rep(i,1,idx)rebuild(i);
rep(i,1,m){
if(qs[i].r<L||qs[i].l>R)continue;
if(qs[i].o==1)modify(max(L,qs[i].l),min(R,qs[i].r),mp[qs[i].x],mp[qs[i].y]);
else query(i,max(L,qs[i].l),min(R,qs[i].r),mp[qs[i].x],mp[qs[i].y]);
}
}
int main(){
read(n),read(m);
rep(i,1,n)read(a[i]);
rep(i,1,m)read(qs[i].o),read(qs[i].l),read(qs[i].r),read(qs[i].x),read(qs[i].y);
int tot=n/B+!!(n%B);
rep(i,1,tot)solve((i-1)*B+1,min(i*B,n));
rep(i,1,m)if(qs[i].o==2)write(qs[i].ans^inf?qs[i].ans:-1,'\n');
return 0;
}

浙公网安备 33010602011771号