BZOJ 1564 二叉查找树

Posted on 2017-03-21 08:17  ziliuziliu  阅读(128)  评论(0编辑  收藏  举报

dp[i][j][k]表示[i,j],子树权值>=k的答案。

注意因为考虑每一层的贡献,因此这个dp和深度无关。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxv 85
#define inf 1000000007
using namespace std;
int n,k,a[maxv],b[maxv],dp[maxv][maxv][maxv],sum[maxv];
struct pnt
{
    int w,val,p;
    friend bool operator < (const pnt &x,const pnt &y)
    {
        return x.w<y.w;
    }
}p[maxv];
int get_dp(int l,int r,int w)
{
    if (dp[l][r][w]) return dp[l][r][w];
    if (l==r) return sum[l]-sum[l-1]+(p[l].val<w)*k;
    if (l>r) return 0;
    dp[l][r][w]=inf;
    for (int i=l;i<=r;i++)
    {
        if (p[i].val>=w)
            dp[l][r][w]=min(dp[l][r][w],get_dp(l,i-1,p[i].val)+get_dp(i+1,r,p[i].val)+(sum[r]-sum[l-1]));
        dp[l][r][w]=min(dp[l][r][w],get_dp(l,i-1,w)+get_dp(i+1,r,w)+(sum[r]-sum[l-1])+k);
    }
    return dp[l][r][w];
}
int main()
{
    scanf("%d%d",&n,&k);
    for (int i=1;i<=n;i++) scanf("%d",&p[i].w);
    for (int i=1;i<=n;i++) {scanf("%d",&a[i]);b[i]=a[i];}
    for (int i=1;i<=n;i++) scanf("%d",&p[i].p);
    sort(b+1,b+n+1);
    for (int i=1;i<=n;i++) p[i].val=lower_bound(b+1,b+n+1,a[i])-b;
    sort(p+1,p+n+1);
    for (int i=1;i<=n;i++) sum[i]=sum[i-1]+p[i].p;
    int mn=inf;
    for (int i=0;i<=n;i++) mn=min(mn,get_dp(1,n,i));
    printf("%d\n",mn);
    return 0;
}