小技巧之树上优化
对于某些树形背包,第二维跟子树大小有关,且不超过\(siz[x]\),
我们原来会写成类似于这样:
for(int i=head[x];i;i=e[i].nxt){
v=e[i].to;
if(v!=fa){
dfs(v,x),o[x]^=1,siz[x]+=siz[e[i].to];
for(int j=n;j>=0;--j) f[o[x]][x][j]=0;
for(int j=n;j>=1;--j)
for(int k=n;k>=0;--k){
f[o[x]][x][j]=(f[o[x]][x][j]+f[o[x]^1][x][j-k]*f[o[v]][v][k])%mod;
if(k>=p) f[o[x]][x][j-k]=(f[o[x]][x][j-k]+f[o[x]^1][x][j-k]*f[o[v]][v][k])%mod;
}
}
}
时间复杂度\(O((\sum_{u=1}^{n}\sum_{v}^{(u,v)\in E} 1)*n*n)=O((n-1)*n*n)\approx O(n^{3})\)
但我们显然可以优化,限制背包大小,如:
for(int i=head[x];i;i=e[i].nxt){
v=e[i].to;
if(v!=fa){
dfs(v,x),o[x]^=1,siz[x]+=siz[e[i].to];
for(int j=siz[x];j>=0;--j) f[o[x]][x][j]=0;
for(int j=siz[x];j>=1;--j)
for(int k=siz[v];k>=0;--k){
f[o[x]][x][j]=(f[o[x]][x][j]+f[o[x]^1][x][j-k]*f[o[v]][v][k])%mod;
if(k>=p) f[o[x]][x][j-k]=(f[o[x]][x][j-k]+f[o[x]^1][x][j-k]*f[o[v]][v][k])%mod;
}
}
}
则对于每个点x遍历的大小则为经过他的无序点对数量
n个点总和为所有无序点对数量,时间复杂度\(O(n^{2})\)