小技巧之树上优化

对于某些树形背包,第二维跟子树大小有关,且不超过\(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})\)

posted @ 2019-10-14 21:30  lsoi_ljk123  阅读(126)  评论(0编辑  收藏  举报