P3631 [APIO2011] 方格染色 Sol
一道推式子+带权并查集的好题
推式子——发现结论
将红色视作1,蓝色视作0,当前位置为(x,y),则由题目可以得到:
\[a_{x,y} \oplus a_{x-1,y} \oplus a_{x,y-1} \oplus a_{x-1,y-1} = 1
\]
同理可得:
\[a_{x-2,y} \oplus a_{x-1,y} \oplus a_{x-2,y-1} \oplus a_{x-1,y-1} = 1
\]
于是有:
\[a_{x-2,y} \oplus a_{x,y} \oplus a_{x,y-1} \oplus a_{x-2,y-1} = 0
\]
推广一下,有:
\[a_{x-2k,y} \oplus a_{x,y} \oplus a_{x,y-1} \oplus a_{x-2k,y-1} = 0
\]
再次推广一下,有:
\[a_{x-2k,y} \oplus a_{x,y} \oplus a_{x,y-t} \oplus a_{x-2k,y-t} = 0
\]
同样的,有:
\[a_{x-t,y-2k} \oplus a_{x-t,y} \oplus a_{x,y-2k} \oplus a_{x,y-2k} = 0
\]
因此可以得到,如果x,y有一个是奇数,就有:
\[a_{x,y} \oplus a_{1,y} \oplus a_{x,1} \oplus a_{1,1} = 0
\]
否则,有:
\[a_{x,y} \oplus a_{1,y} \oplus a_{x,1} \oplus a_{1,1} = 1
\]
由此,我们可以发现,只用第一行,第一列的内容,就可以知道整个矩阵。
带权并查集维护
题目中的k个限制变成了对x,y的限制,可以使用并查集进行维护。
具体的,设置 \(g_i\),表示 \(val_i \oplus val_{rt}\),其中 \(rt\) 表示并查集上的最高父亲,显然的,\(g_{rt}=0\)。在并查集的find中,我们就要这样写:
int find(int x){
if(x == fa[x]) return x;
int tmp = fa[x];
fa[x] = find(fa[x]);
g[x] ^= g[tmp];
return fa[x];
}
理解一下,\(g_x=val_{x} \oplus val_{fa}\),\(g_{fa}=val_{fa} \oplus val_{rt}\),则\(g_x \oplus g_{fa}=val_{x} \oplus val_{fa} \oplus val_{fa} \oplus val_{rt}=val_{x} \oplus val_{rt}\),可以发现是对的。
再看看计算部分。
for(int i=1;i<=k;i++){
int u = find(x[i]),v = find(y[i] + n),num = val ^ c[i];
if(x[i] % 2 == 0 && y[i] % 2 == 0) num ^= 1;
if(u != v){
fa[u] = v;
g[u] = num ^ g[x[i]] ^ g[n + y[i]];
}
else if(num != g[x[i]] ^ g[n + y[i]])
return 0;
}
先理解g[u] = num ^ g[x[i]] ^ g[n + y[i]];,首先回顾一下,我们要求\(val_{x,1} \oplus val_{1,y} \oplus num=0\),而有以下关系
- \(g_x=val_x \oplus val_{u}\)
- \(g_y=val_y \oplus val_{v}\)
- \(num=val_{x} \oplus val_{y}\)
- \(g_u=val_u \oplus val_{v}\)(这是要实现的)
因此:\(g_u=num \oplus g_{x} \oplus g_{y}=val_x \oplus val_y \oplus val_x \oplus val_u \oplus val_y \oplus val_v=val_u \oplus val_v\)。
所以这是对的。

浙公网安备 33010602011771号