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\n",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 }

 

posted @ 2017-08-03 20:30  PIPIBoss  阅读(183)  评论(0编辑  收藏  举报