题解 P8427 [COI 2020] Paint
终于传上来了,咕咕了两年了属实不容易。
考虑一个很裸的暴力,我们每次 BFS 然后更新染色。时间复杂度显然很劣。
接下来我们考虑根号分治。(下面称相邻的连通块为邻居)
考虑面积
考虑面积
为了支持这个哈希表的更新,我们还必须对于所有块去维护其邻居中大块的集合,所以这里空间复杂度上界同
再考虑两个块的合并,我们采用启发式合并,每次将小的集合连向大的集合。
由于每个连通块的合并次数不会超过
实现时细节还是很多的。自己注意下别写错复杂度就行。
//QwQcOrZ yyds!!!
#include<bits/stdc++.h>
#define ll long long
#define F(i,a,b) for (int i=(a);i<=(b);++i)
#define R(i,a,b) for (int i=(a);i<(b);++i)
#define D(i,a,b) for (int i=(a);i>=(b);i--)
#define go(i,x) for (int i=head[x];i;i=e[i].nx)
#define mp make_pair
#define pb push_back
#define pa pair < int,int >
#define fi first
#define se second
#define re register
#define be begin()
#define en end()
#define sqr(x) ((x)*(x))
#define ret return puts("-1"),0;
#define put putchar('\n')
#define inf 1000000005
#define mod 998244353
//#define int ll
#define N 200005
using namespace std;
inline char gc(){static char buf[100000],*p1=buf,*p2=buf;return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;}
//#define gc getchar
inline ll read(){char c=gc();ll su=0,f=1;for (;c<'0'||c>'9';c=gc()) if (c=='-') f=-1;for (;c>='0'&&c<='9';c=gc()) su=su*10+c-'0';return su*f;}
inline void write(ll x){if (x<0){putchar('-');write(-x);return;}if (x>=10) write(x/10);putchar(x%10+'0');}
inline void writesp(ll x){write(x),putchar(' ');}
inline void writeln(ll x){write(x);putchar('\n');}
int n,m,Q,fa[N],neg[N],xx,yy,col,ID,cnt;
const int c[]={0,0,0,-1,1},d[]={0,-1,1,0,0};
const int B=0;
vector<vector<int> >a,bel;
struct
{
int large,col;
vector<pa>nod;
vector<int>bignb;
map<int,vector<int>>lis;
}S[N];
int gf(int x)
{
if (x==fa[x]) return x;
return gf(fa[x]);
}
void dfs(int x,int y)
{
S[cnt].nod.push_back({x,y});
bel[x][y]=cnt;
for (int i=1;i<=4;++i)
{
int u=x+c[i],v=y+d[i];
if (u>=1&&u<=n&&v>=1&&v<=m)
{
if (a[u][v]==a[x][y]&&!bel[u][v])
{
dfs(u,v);
}
}
}
}
inline void turn_to_big(int now)
{
S[now].large=1;
vector<int>nowb;
ID++;
for (auto u:S[now].nod)
{
for (int j=1;j<=4;++j)
{
int x=u.fi+c[j],y=u.se+d[j];
if (x>=1&&x<=n&&y>=1&&y<=m)
{
if (bel[x][y]==now) continue;
int v=bel[x][y];
if (neg[v]==ID) continue;
neg[v]=ID;
S[v].bignb.push_back(now);
S[now].lis[S[v].col].push_back(v);
}
}
}
}
inline int merge(int x,int y)
{
if (!S[x].large&&S[y].large) turn_to_big(x);
else
if (S[x].large&&!S[y].large) turn_to_big(y);
if (S[x].nod.size()>S[y].nod.size()) swap(x,y);
fa[x]=y;
for (auto u:S[x].nod)
{
bel[u.fi][u.se]=y;
S[y].nod.push_back(u);
}
vector<pa>().swap(S[x].nod);
if (S[x].bignb.size()>S[y].bignb.size())
S[x].bignb.swap(S[y].bignb);
for (auto u:S[x].bignb)
{
S[y].bignb.push_back(u);
}
vector<int>().swap(S[x].bignb);
re vector<int>nownb;
ID++;
for (auto u:S[y].bignb)
{
int uu=gf(u);
if (uu!=y&&neg[uu]!=ID)
{
neg[uu]=ID;
nownb.push_back(uu);
}
}
vector<int>().swap(S[y].bignb);
S[y].bignb=nownb;
for (auto u:S[x].lis)
{
int nowcol=u.fi;
auto &lis1=u.se;
auto &lis2=S[y].lis[nowcol];
if (lis1.size()>lis2.size()) lis1.swap(lis2);
for (auto v:lis1)
{
lis2.push_back(v);
}
vector<int>().swap(lis1);
}
S[x].lis.clear();
if (!S[y].large&&S[y].nod.size()>B) turn_to_big(y);
return y;
}
signed main()
{
n=read(),m=read();
a.resize(n+10);
for (re int i=1;i<=n;++i) a[i].resize(m+10);
bel.resize(n+10);
for (re int i=1;i<=n;++i) bel[i].resize(m+10);
for (re int i=1;i<=n;++i)
for (re int j=1;j<=m;++j)
a[i][j]=read();
for (re int i=1;i<=n;++i)
for (re int j=1;j<=m;++j)
if (!bel[i][j])
{
bel[i][j]=++cnt;
S[cnt].large=0;
S[cnt].nod.clear();
S[cnt].bignb.clear();
S[cnt].lis.clear();
S[cnt].col=a[i][j];
dfs(i,j);
}
for (re int i=1;i<=cnt;++i)
{
ID++;
for (auto u:S[i].nod)
{
for (re int j=1;j<=4;++j)
{
int x=u.fi+c[j],y=u.se+d[j];
if (x>=1&&x<=n&&y>=1&&y<=m)
{
if (bel[x][y]==i) continue;
int v=bel[x][y];
if (neg[v]==ID) continue;
neg[v]=ID;
if (S[v].nod.size()>B) S[i].bignb.push_back(v);
if (S[i].nod.size()>B)
S[i].lis[S[v].col].push_back(v);
}
}
}
}
for (re int i=1;i<=cnt;++i)
{
if (S[i].nod.size()>B) turn_to_big(i);
fa[i]=i;
}
// return 0;
Q=read();
while (Q--)
{
xx=read(),yy=read(),col=read();
re int now=bel[xx][yy];
// cout<<now<<" "<<S[now].large<<endl;
if (!S[now].large)
{
re vector<int>nowb;
ID++;
for (auto u:S[now].nod)
{
for (re int j=1;j<=4;++j)
{
int x=u.fi+c[j],y=u.se+d[j];
if (x>=1&&x<=n&&y>=1&&y<=m)
{
if (bel[x][y]==now) continue;
int v=bel[x][y];
if (neg[v]==ID) continue;
neg[v]=ID;
if (S[v].col==col) nowb.push_back(v);
}
}
}
for (auto u:nowb)
{
now=merge(now,u);
}
nowb.clear();
ID++;
for (auto u:S[now].bignb)
{
int uu=gf(u);
if (uu!=now&&neg[uu]!=ID)
{
neg[uu]=ID;
nowb.push_back(uu);
}
}
S[now].bignb.clear();
S[now].bignb=nowb;
S[now].col=col;
for (auto u:S[now].bignb)
{
S[u].lis[S[now].col].push_back(now);
}
}
else
{
re vector<int>nowb;
++ID;
for (auto u:S[now].lis[col])
{
int uu=gf(u);
if (uu!=now&&neg[uu]!=ID)
{
neg[uu]=ID;
if (S[uu].col==col) nowb.push_back(uu);
}
}
S[now].lis[col].clear();
S[now].lis[col]=nowb;
// cout<<"!"<<endl;
for (auto u:nowb)
{
// cout<<u<<endl;
now=merge(now,u);
}
nowb.clear();
ID++;
for (auto u:S[now].bignb)
{
int uu=gf(u);
if (uu!=now&&neg[uu]!=ID)
{
neg[uu]=ID;
nowb.push_back(uu);
}
}
S[now].bignb.clear();
S[now].bignb.swap(nowb);
S[now].col=col;
for (auto u:S[now].bignb)
{
S[u].lis[S[now].col].push_back(now);
}
}
}
for (re int i=1;i<=n;++i)
{
for (re int j=1;j<=m;++j)
writesp(S[bel[i][j]].col);
puts("");
}
}