BZOJ4446: [Scoi2015]小凸玩密室
用ui,j表示走完i的子树后走到i的深度为j的祖先的兄弟的最小代价;
用vi,j表示走完i的子树后走到i的深度为j的祖先的最小代价,用u算出v。
枚举起点,计算答案。
#include<algorithm> #include<cstdio> using std::min; typedef long long ll; const int N=2e5+5; ll a[N],b[N],c[N],f[N][19][2]; int main(){ struct{ operator int(){ int x=0,c=getchar(); while(c<48)c=getchar(); while(c>47) x=x*10+c-48,c=getchar(); return x; } }it; int n=it; for(int i=1;i<=n;++i) a[i]=it; for(int i=2;i<=n;++i){ b[i]=it; c[i]=c[i>>1]+b[i]; } for(int i=n;i;--i) for(int j=1;i>>j-1;++j) if(i<<1>n){ f[i][j][0]=(c[i]-c[i>>j]+b[i>>j-1^1])*a[i>>j-1^1]; f[i][j][1]=(c[i]-c[i>>j])*a[i>>j]; }else{ f[i][j][0]=i<<1<n?min(b[i<<1]*a[i<<1]+f[i<<1][1][0]+f[i<<1^1][j+1][0],b[i<<1^1]*a[i<<1^1]+f[i<<1^1][1][0]+f[i<<1][j+1][0]):b[i<<1]*a[i<<1]+f[i<<1][j+1][0]; f[i][j][1]=i<<1<n?min(b[i<<1]*a[i<<1]+f[i<<1][1][0]+f[i<<1^1][j+1][1],b[i<<1^1]*a[i<<1^1]+f[i<<1^1][1][0]+f[i<<1][j+1][1]):b[i<<1]*a[i<<1]+f[i<<1][j+1][1]; } if(~n&1) f[n^1][2][1]=b[n>>1]*a[n>>2]; ll z=1e18; for(int i=n;i;--i){ ll s=f[i][1][1]; for(int j=i;j>>1;j>>=1) s+=b[j^1]*a[j^1]+f[j^1][2][1]; z=min(z,s); } printf("%lld\n",z); }