[loj3626]愚蠢的在线法官

交换$a_{x}$和$a_{y}$会同时交换行列式的两行和两列,不改变行列式的值,不妨将$a_{i}$按照dfs序排序

此时,$k$子树内的$a_{i}$构成连续区间,设其为区间$[l_{k},r_{k}]$,并记录$a_{[l_{k},r_{k}]}$所对应的行列式

考虑转移,将$[l_{k},r_{k}]$按照$k$和不同的子树划分为若干段,前者可以直接处理,后者递归子树处理

考虑合并,问题即求$\det \left(\begin{array}{ll}A&B\\C&D\end{array}\right)$(已知$\det A,D$且$B,C$中所有元素均为$v_{k}$)

记$A_{t}$为将$A$中所有元素减去$t$所得到的行列式,将其代入行列式的式子,不难得到
$$
\begin{array}{ll}\det A_{t}&=\sum_{P}(-1)^{inv(P)}\prod_{i=1}^{n}(A_{i,P_{i}}-t)\\&=\sum_{P}(-1)^{inv(P)}\sum_{S\subseteq [1,n]}(-t)^{|S|}\prod_{x\not\in S}A_{x,P_{x}}\\&=\sum_{S\subseteq [1,n]}(-t)^{|S|}\sum_{P}(-1)^{inv(P)}\prod_{x\not\in S}A_{x,P_{x}}\end{array}
$$
对于最后一项,当$|S|\ge 2$时,任取$x,y\in S$,交换$P_{x}$和$P_{y}$后即相互抵消,因此后者为0

当$|S|<2$时,对$S=\empty$和$S=\{i\}$​分别处理,即
$$
\det A_{t}=\det A-t\sum_{i=1}^{n}\sum_{P}(-1)^{inv(P)}\prod_{x\ne i}A_{x,P_{x}}
$$
记后者为$\det_{s}A$,即将任意一行所有元素均变为1后的行列式之和,将其与$\det A$一起维护

同时,对其分别做以下两个变形:1.移项;2.代入$A=A_{t_{-t}}$​,即
$$
\begin{cases}\det A=\det A_{t}+t\det_{s}A\\\det A=\det A_{t}+t\det_{s}A_{t}\end{cases}
$$
两式相减,即解得$\det_{s}A=\det_{s}A_{t}$(通俗的来说,即所有元素同时加上一个值后不改变$\det_{s}$)

综上,即得到转移为
$$
\begin{array}{ll}\det_{s}\left(\begin{array}{ll}A&B\\C&D\end{array}\right)&=\det_{s}\left(\begin{array}{ll}A&B\\C&D\end{array}\right)_{v_{k}}=\det_{s}\left(\begin{array}{ll}A_{v_{k}}&O\\O&D_{v_{k}}\end{array}\right)\\&=\det_{s}A \times \det D_{v_{k}}+\det A_{v_{k}}\times \det_{s}D\\&=\det_{s}A\times (\det D-v_{k}\det_{s}D)+(\det A-v_{k}\det_{s}A)\det_{s}D\end{array}
$$

$$
\begin{array}{ll}\det \left(\begin{array}{ll}A&B\\C&D\end{array}\right)&=\det \left(\begin{array}{ll}A&B\\C&D\end{array}\right)_{v_{k}}+v_{k}\det_{s}\left(\begin{array}{ll}A&B\\C&D\end{array}\right)\\&=\det A_{v_{k}}\times \det D_{v_{k}}+v_{k}\det_{s}\left(\begin{array}{ll}A&B\\C&D\end{array}\right)\\&=(\det A-v_{k}\det_{s}A)(\det D-v_{k}\det_{s}D)+v_{k} \det_{s}\left(\begin{array}{ll}A&B\\C&D\end{array}\right)\end{array}
$$

时间复杂度为$o(n)$,可以通过

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define N 500005
 4 #define mod 998244353
 5 #define ll long long
 6 vector<int>e[N];
 7 int n,m,x,y,v[N],cnt[N],vis[N],g[N],f[N];
 8 void dfs(int k,int fa){
 9     vis[k]=f[k]=g[k]=0;
10     if (cnt[k])vis[k]=1,f[k]=v[k],g[k]=1;
11     for(int i=0;i<e[k].size();i++)
12         if (e[k][i]!=fa){
13             dfs(e[k][i],k);
14             if (!vis[e[k][i]])continue;
15             if (!vis[k])vis[k]=1,f[k]=f[e[k][i]],g[k]=g[e[k][i]];
16             else{
17                 int s1=(f[k]-(ll)v[k]*g[k]%mod+mod)%mod;
18                 int s2=(f[e[k][i]]-(ll)v[k]*g[e[k][i]]%mod+mod)%mod;
19                 int gg=((ll)g[k]*s2+(ll)g[e[k][i]]*s1)%mod;
20                 f[k]=((ll)s1*s2+(ll)v[k]*gg)%mod,g[k]=gg;
21             }
22         }
23 }
24 int main(){
25     scanf("%d%d",&n,&m);
26     for(int i=1;i<=n;i++)scanf("%d",&v[i]);
27     for(int i=1;i<=m;i++){
28         scanf("%d",&x);
29         cnt[x]++;
30     }
31     for(int i=1;i<n;i++){
32         scanf("%d%d",&x,&y);
33         e[x].push_back(y),e[y].push_back(x);
34     }
35     for(int i=1;i<=n;i++)
36         if (cnt[i]>1){
37             printf("0\n");
38             return 0;
39         }
40     dfs(1,0);
41     printf("%d\n",f[1]);
42     return 0;
43 }
View Code

 

posted @ 2022-02-18 16:05  PYWBKTDA  阅读(201)  评论(0编辑  收藏  举报