AT_abc435_g [ABC435G] Domino Arrangement 题解
Phoenix_2010
·
·
题解
题目限制相当于每一个极长同色连续段(不包括无色)长度都是 2。
显然是一个划分子段问题。考虑 dp。设 dp_i 表示前 i 个格子的方案数。显然 dp_0=1。考虑转移:
首先,第 i 格可以不涂颜色,dp_i \leftarrow dp_{i-1}。
然后,第 i 格和 i-1 格可以涂上相同颜色,dp_i \leftarrow dp_i+dp_{i-2} \times cnt_{i-1,i},其中 cnt_{i,j} 表示可以给 [i,j] 上色的有几种。
但是这样会考虑到一种颜色同时给 [i-3,i] 上色的情况,需要减去,dp_i \leftarrow dp_i-dp_{i-4} \times cnt_{i-3,i}。
但是当 [i-5,i] 为同种颜色时,第一次没有考虑这种情况,因为 [i-5,i-2] 同色是不合法的。而第二次考虑了这种情况,因为 [i-5,i-4] 同色是合法的。所以又需要加回来。
所以此时就有容斥的影子了。具体的,
dp_i=dp_{i-1}+\sum_{j=1}^{\lfloor\frac{i}{2}\rfloor}(-1)^{j-1}\cdot dp_{i-2j}\cdot cnt_{i-2j+1,i}
考虑优化。
首先 dp_{i-2j} 这一项直接分最后一段的奇偶性前缀和维护即可。考虑怎么维护这个 cnt。
一个常见套路是维护以 i 为结尾的 cnt,并考虑 i 移动时的贡献。当 i \rightarrow i+1 时,我们会新加入一个 cnt_{i+1,i+1},即 i+1 被覆盖次数,这个差分即可。然后对于每个以 i 为结尾的 [l,r],将不再包含以 i+1 结尾的区间,失去贡献,使得 \forall j \in [l,i], cnt_{j,i+1} \leftarrow cnt_{j,i}-1。
把上述二者结合一下,设 c_0,c_1 表示以 i 为结尾,最后一段长度为偶数,奇数时的总贡献。当 i \rightarrow i+1 时:
最后一段长度奇偶性改变,交换 c_0,c_1。
加入了 cnt_{i+1,i+1},此时 c_1 中所有的贡献需要变为原来的相反数(因为多了一段),即 c_1 \leftarrow cnt_{i+1,i+1} \times dp_{i-1}
对于每个以 i 为结尾的 [l,r],由于分了奇偶性,而且同奇偶性中分正负,所以要按照长度除以 4 的余数分类讨论。
由于 cnt 是成段减一的,不妨设前缀和数组 s_{i,0/1}:
s_{i,0}=\sum_{j=1}^{\lfloor\frac{i}{2}\rfloor}(-1)^{j-1}\cdot dp_{i-2j}\\
s_{i,1}=\sum_{j=1}^{\lfloor\frac{i}{2}\rfloor}(-1)^{j-1}\cdot dp_{i-2j+1}
当 $(r-l+1)\bmod4=1$ 时,
对于 $c_0$,会失去 $l,l+2,\dots,i-2$ 的贡献,且 $s_{i,0}$ 和 $s_{l-1,1}$ 相减才会抵消。所以 $c_0 \leftarrow c_0-(s_{i,0}-s_{l-1,1})$。
对于 $c_1$,会失去 $l-1,l+1,\dots,i-1$ 的贡献,且 $s_{i,1}$ 和 $s_{l-1,0}$ 相加才会抵消。所以 $c_1 \leftarrow c_1-(s_{i,1}+s_{l-1,0})$。
当 $(r-l+1)\bmod4=2$ 时,
对于 $c_0$,会失去 $l-1,l+1,\dots,i-2$ 的贡献,且 $s_{i,0}$ 和 $s_{l-1,0}$ 相加才会抵消。所以 $c_0 \leftarrow c_0-(s_{i,0}+s_{l-1,0})$。
对于 $c_1$,会失去 $l,l+2,\dots,i-1$ 的贡献,且 $s_{i,1}$ 和 $s_{l-1,1}$ 相加才会抵消。所以 $c_1 \leftarrow c_1-(s_{i,1}+s_{l-1,1})$。
当 $(r-l+1)\bmod4=3$ 时,
对于 $c_0$,会失去 $l,l+2,\dots,i-2$ 的贡献,且 $s_{i,0}$ 和 $s_{l-1,1}$ 相加才会抵消。所以 $c_0 \leftarrow c_0-(s_{i,0}+s_{l-1,1})$。
对于 $c_1$,会失去 $l-1,l+1,\dots,i-1$ 的贡献,且 $s_{i,1}$ 和 $s_{l-1,0}$ 相减才会抵消。所以 $c_1 \leftarrow c_1-(s_{i,1}-s_{l-1,0})$。
当 $(r-l+1)\bmod4=0$ 时,
对于 $c_0$,会失去 $l-1,l+1,\dots,i-2$ 的贡献,且 $s_{i,0}$ 和 $s_{l-1,0}$ 相减才会抵消。所以 $c_0 \leftarrow c_0-(s_{i,0}-s_{l-1,0})$。
对于 $c_1$,会失去 $l,l+2,\dots,i-1$ 的贡献,且 $s_{i,1}$ 和 $s_{l-1,1}$ 相减才会抵消。所以 $c_1 \leftarrow c_1-(s_{i,1}-s_{l-1,1})$。
可以自行画图加深理解。
然后就做完了,整个 dp 是 $O(n)$ 的,计算贡献总共是 $O(m)$ 的,因为每个 $[l,r]$ 只会在 $i=r$ 时被考虑一次,所以时间复杂度 $O(n+m)$。
```cpp
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=5e5+5,mod=998244353;
int n,m,l[N],r[N],d[N];ll dp[N],c[2],s[N][2];vector<int> del[N];
int main()
{
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
cin>>n>>m;
for(int i=1;i<=m;i++) cin>>l[i]>>r[i],d[l[i]]++,del[r[i]].push_back(l[i]);
dp[0]=1;
for(int i=1,tmp=0;i<=n;i++)
{
tmp+=d[i];//差分,计算cnt[i][i]
swap(c[0],c[1]);c[1]=(tmp*dp[i-1]%mod-c[1]+mod)%mod;
s[i][0]=s[i-1][1],s[i][1]=s[i-1][0];s[i][1]=(dp[i-1]-s[i][1]+mod)%mod;
//变化长度奇偶性,并加入[i,i]的贡献
dp[i]=(dp[i-1]+c[0])%mod;//答案即为最后一段长度为偶数的情况
for(auto l:del[i])
{
tmp--;
int len=i-l+1;
if(len%4==1) (c[0]-=s[i][0]-s[l-1][1]-mod)%=mod,(c[1]-=s[i][1]+s[l-1][0]-2*mod)%=mod;
else if(len%4==2) (c[0]-=s[i][0]+s[l-1][0]-2*mod)%=mod,(c[1]-=s[i][1]+s[l-1][1]-2*mod)%=mod;
else if(len%4==3) (c[0]-=s[i][0]+s[l-1][1]-2*mod)%=mod,(c[1]-=s[i][1]-s[l-1][0]-mod)%=mod;
else (c[0]-=s[i][0]-s[l-1][0]-mod)%=mod,(c[1]-=s[i][1]-s[l-1][1]-mod)%=mod;
}
}
cout<<dp[n];
return 0;
}
```