• bzoj 1564: [NOI2009]二叉查找树


    Description

    Input

    Output

    只有一个数字,即你所能得到的整棵树的访问代价与额外修改代价之和的最小值。

    Sample Input

    4 10
    1 2 3 4
    1 2 3 4
    1 2 3 4

    Sample Output

    29

    HINT

    输入的原图是左图,它的访问代价是1×1+2×2+3×3+4×4=30。最佳的修改方案是把输入中的第3个结点的权值改成0,得到右图,访问代价是1×2+2×3+3×1+4×2=19,加上额外修改代价10,一共是29。

    题解:

    这题枚举顺序和边界都好麻烦.

    关键得意识到:数据值一定->二叉搜索树->中序遍历为从小到大排序->子树对应区间->区间dp.

    类似于加分二叉树.....扯远了....

    那么果断定义f[l][r][i]为区间[l,r]中,所有节点最大值为i时的最小代价

    显然 如果val[root]>=val[i] 那么就可以直接转移:f[l][j-1][id[j]]+f[j+1][r][id[j]]+sum[r]-sum[l-1]  id为离散后排名,j为root

    不满足的话加上k即可,相当于把root权值改为i:k+f[l][j-1][i]+f[j+1][r][i]+sum[r]-sum[l-1]

    代码里面在搞事,不要去参考....

     1 #include <algorithm>
     2 #include <iostream>
     3 #include <cstdlib>
     4 #include <cstring>
     5 #include <cstdio>
     6 #include <cmath>
     7 using namespace std;
     8 typedef long long ll;
     9 const int N=75;
    10 const ll inf=2e16;
    11 ll f[N][N][N];
    12 struct node{
    13     int x,w,p;
    14 }a[N];
    15 int b[N];
    16 bool comp(const node &pp,const node &qq){
    17     return pp.x<qq.x;
    18 }
    19 int id[N],n;ll sum[N];
    20 int midit(int x){
    21     int l=1,r=n,mid;
    22     while(l<=r){
    23         mid=(l+r)>>1;
    24         if(b[mid]==x)return mid;
    25         if(b[mid]>x)r=mid-1;
    26         else l=mid+1;
    27     }
    28     return 0;
    29 }
    30 void work()
    31 {
    32     int D;
    33     scanf("%d%d",&n,&D);
    34     for(int i=1;i<=n;i++)scanf("%d",&a[i].x);
    35     for(int i=1;i<=n;i++)scanf("%d",&a[i].w);
    36     for(int i=1;i<=n;i++)scanf("%d",&a[i].p);
    37     sort(a+1,a+n+1,comp);
    38     for(int i=1;i<=n;i++)b[i]=a[i].w;
    39     sort(b+1,b+n+1);
    40     for(int i=0;i<=n+1;i++)
    41         for(int j=0;j<=n+1;j++)
    42             for(int k=0;k<=n+1;k++)
    43                 f[i][j][k]=inf;
    44     for(int i=1;i<=n;i++)id[i]=midit(a[i].w),sum[i]=sum[i-1]+a[i].p;
    45     register int l,r,i,k,j;register ll tmp;
    46     for(i=0;i<=n;i++)
    47         for(j=0;j<=n;j++)
    48             f[i+1][i][j]=0;
    49     for(i=n;i>=0;i--){
    50         for(k=1;k<=n;k++){
    51             for(l=1;l<=n-k+1;l++){
    52                 r=l+k-1;
    53                 for(j=l;j<=r;j++){
    54                     if(id[j]>=i){
    55                         tmp=(f[l][j-1][id[j]]+f[j+1][r][id[j]]+sum[r]-sum[l-1]);
    56                         if(tmp<f[l][r][i])
    57                             f[l][r][i]=tmp;
    58                     }
    59                     tmp=D+f[l][j-1][i]+f[j+1][r][i]+sum[r]-sum[l-1];
    60                       if(tmp<f[l][r][i])
    61                           f[l][r][i]=tmp;
    62                 }
    63             }
    64         }
    65     }
    66     printf("%lld
    ",f[1][n][0]);
    67 }
    68 int main()
    69 {
    70     freopen("treapmod.in","r",stdin);
    71     freopen("treapmod.out","w",stdout);
    72     work();
    73     return 0;
    74 }
  • 相关阅读:
    怎么解决Chrome浏览器崩溃“STATUS_INVALID_IMAGE_HASH”的问题
    Windows下PHP如何选择Thread Safe和Non ThreadSafe版本
    Windows环境下安装Yaf框架
    创建Redis-Cluster集群常见问题-解决方案
    Linxu下PHP版本升级
    Linxu下Yii2的POST提交被拒经历
    彻底搞懂 Redis 事务
    python模块之psutil详解
    iptables学习笔记
    incaseformat 病毒事件企业解决流程
  • 原文地址:https://www.cnblogs.com/Yuzao/p/7281736.html
Copyright © 2020-2023  润新知