#include<cstdio> #include<string> #include<cstring> #include<iostream> #include<algorithm> #define rint register int #define min(a,b) (a<b? a:b) using namespace std; struct node{int x,y,z;}a[100]; int f[100][100][100]; int n,K; inline int read() { int w=1,ans=0; char ch=getchar(); while(!isdigit(ch)) {if (ch=='-') w=-1; ch=getchar();} while(isdigit(ch)) {ans=(ans<<3)+(ans<<1)+(ch^48); ch=getchar();} return ans*w; } inline bool cmp(node a,node b) { return a.y<b.y; } inline bool cmp2(node a,node b) { return a.x<b.x; } int main() { //freopen("tree.in","r",stdin); //freopen("tree.out","w",stdout); n=read();K=read(); for (int i=1;i<=n;i++) a[i].x=read();//數據 for (int i=1;i<=n;i++) a[i].y=read();//權值 for (int i=1;i<=n;i++) a[i].z=read();//訪問頻度 sort(a+1,a+n+1,cmp);//按權值排序,離散化 for (int i=1;i<=n;i++) a[i].y=i;//將權值離散化 sort(a+1,a+n+1,cmp2); for (int i=1;i<=n;i++) a[i].z+=a[i-1].z;//前綴和 memset(f,0x7f,sizeof f); for (int i=1;i<=n+1;i++) for (int w=0;w<=n;w++) f[i][i-1][w]=0; for (rint w=n;~w;w--)//~w指w非零,區間內全部權值大於w for (rint i=n;i;i--) for (rint j=i;j<=n;j++) for (rint k=i;k<=j;k++)//區間dp枚舉根節點位置 { if (a[k].y>=w) f[i][j][w]=min(f[i][j][w],f[i][k-1][a[k].y]+f[k+1][j][a[k].y]+a[j].z-a[i-1].z); //a[j].z-a[i-1].z:當樹深加1,把每一個訪問頻度都再加一次 f[i][j][w]=min(f[i][j][w],f[i][k-1][w]+f[k+1][j][w]+a[j].z-a[i-1].z+K); } printf("%d",f[1][n][1]); return 0; }