密室玩小凸。
完全二叉树关于复杂度的两个性质:
1.所有点的深度和为$O(nlog n)$
2.所有点的子树内的叶子个数和为$O(nlog n)$
根据这两个性质可以分别解决此题。
下面使用第二个性质,参考:https://www.cnblogs.com/Gloid/p/9874570.html
f[i][j]表示从i点开始,遍历i的子树,最后在j停止的最优解(其中j为i的子树中的某个叶子)。
g[i][j]表示从i的子树中某个点开始,遍历i的子树,最后在j停止的最优解。
f转移考虑四种情况:
点亮左子树,点亮i,点亮右子树,或反之。
点亮i,点亮左子树,点亮右子树,或反之。
g转移考虑同样的四种情况,再与f取min。
注意当i为叶子或只有一个儿子时特殊处理。
细节要考虑清楚,为了保证空间使用vector记录子树内的叶子。
小凸玩我。
1 #include<cstdio> 2 #include<vector> 3 #include<algorithm> 4 #define rep(i,l,r) for (int i=(l); i<=(r); i++) 5 typedef long long ll; 6 using namespace std; 7 8 const int N=200010; 9 const ll inf=1e16; 10 int n,x; 11 ll ans,v[N],rlen[N],llen[N],d[N]; 12 vector<int>son[N]; 13 vector<ll>f[N],g[N]; 14 15 void dfs(int x){ 16 int ls=x<<1,rs=ls|1; 17 if (ls>n){ son[x].push_back(x); f[x].push_back(0); g[x].push_back(0); return; } 18 d[ls]=d[x]+llen[x]; dfs(ls); 19 if (rs>n){ 20 int lm=(int)son[ls].size()-1; ll mn=inf; 21 rep(i,0,lm) son[x].push_back(son[ls][i]),mn=min(mn,f[ls][i]+(d[son[ls][i]]-d[x])*v[x]); 22 rep(i,0,lm) f[x].push_back(f[ls][i]+llen[x]*v[ls]),g[x].push_back(f[x][i]); 23 son[x].push_back(x); f[x].push_back(inf); g[x].push_back(mn); 24 return; 25 } 26 d[rs]=d[x]+rlen[x]; dfs(rs); 27 int lm=son[ls].size()-1,rm=son[rs].size()-1; 28 ll mn1=inf,mn2=inf,mn3=inf,mn4=inf; 29 rep(i,0,lm) son[x].push_back(son[ls][i]),mn1=min(mn1,f[ls][i]+(d[son[ls][i]]+d[rs]-2*d[x])*v[rs]); 30 rep(i,0,rm) son[x].push_back(son[rs][i]),mn2=min(mn2,f[rs][i]+(d[son[rs][i]]+d[ls]-2*d[x])*v[ls]); 31 rep(i,0,lm) f[x].push_back(rlen[x]*v[rs]+mn2+f[ls][i]),mn3=min(mn3,g[ls][i]+(d[son[ls][i]]-d[x])*v[x]); 32 rep(i,0,rm) f[x].push_back(llen[x]*v[ls]+mn1+f[rs][i]),mn4=min(mn4,g[rs][i]+(d[son[rs][i]]-d[x])*v[x]); 33 rep(i,0,lm) g[x].push_back(min(mn4+llen[x]*v[ls]+f[ls][i],f[x][i])); 34 rep(i,0,rm) g[x].push_back(min(mn3+rlen[x]*v[rs]+f[rs][i],f[x][lm+i+1])); 35 } 36 37 int main(){ 38 freopen("bzoj4446.in","r",stdin); 39 freopen("bzoj4446.out","w",stdout); 40 scanf("%d",&n); 41 rep(i,1,n) scanf("%lld",&v[i]); 42 rep(i,2,n){ 43 scanf("%d",&x); 44 if (i&1) rlen[i/2]=x; else llen[i/2]=x; 45 } 46 dfs(1); ans=inf; int tmp=(int)g[1].size()-1; 47 rep(i,0,tmp) ans=min(ans,g[1][i]); 48 printf("%lld ",ans); 49 return 0; 50 }