1564: [NOI2009]二叉查找树 - BZOJ

Description

1564: [NOI2009]二叉查找树 - BZOJ


Input

1564: [NOI2009]二叉查找树 - BZOJ


Output
只有一个数字,即你所能得到的整棵树的访问代价与额外修改代价之和的最小值。
Sample Input
4 10
1 2 3 4
1 2 3 4
1 2 3 4
Sample Output
29
HINT
1564: [NOI2009]二叉查找树 - BZOJ
输入的原图是左图,它的访问代价是1×1+2×2+3×3+4×4=30。最佳的修改方案是把输入中的第3个结点的权值改成0,得到右图,访问代价是1×2+2×3+3×1+4×2=19,加上额外修改代价10,一共是29。

 

感觉莫名其妙的A了

我设的状态是f[l,r,k]表示区间[l,r]的元素权值都大于等于k时的最小访问代价之和

然后枚举某个点作为根

1.这个点的权值<k,那么就花费K改成k,f[l,r,k]=min(f[l,r,k],f[l,x-1,k]+f[x+1,r,k]+s[l,r]+K)

2.这个点权值>=k,那么我们可以不花费,也可以花费K改成k,f[l,r,k]=min(f[l,r,k],f[l,x-1,k]+f[x+1,r,k]+s[l,r]+K,f[l,x-1,v[x]]+f[x+1,r,v[x]]+s[l,r])

 1 const

 2     maxn=75;

 3 type

 4     node=record

 5         x,v,c:longint;

 6         flag:boolean;

 7     end;

 8 var

 9     f:array[0..maxn,0..maxn,0..maxn]of longint;

10     a:array[0..maxn]of node;

11     s:array[0..maxn]of longint;

12     n,p,ans:longint;

13  

14 procedure swap(var x,y:node);

15 var

16     t:node;

17 begin

18     t:=x;x:=y;y:=t;

19 end;

20  

21 procedure down(var x:longint;y:longint);

22 begin

23     if x>y then x:=y;

24 end;

25  

26 procedure init;

27 var

28     i,j,cnt,min:longint;

29 begin

30     read(n,p);

31     for i:=1 to n do read(a[i].x);

32     for i:=1 to n do read(a[i].v);

33     for i:=1 to n do read(a[i].c);

34     for i:=n downto 2 do

35         for j:=1 to i-1 do

36             if a[j].x>a[j+1].x then swap(a[j],a[j+1]);

37     for i:=1 to n do s[i]:=s[i-1]+a[i].c;

38     cnt:=0;j:=1;

39     while cnt<n do

40         begin

41             min:=maxlongint;

42             for i:=1 to n do

43                 if a[i].flag=false then down(min,a[i].v);

44             for i:=1 to n do

45                 if (a[i].flag=false) and (a[i].v=min) then

46                 begin

47                     inc(cnt);

48                     a[i].flag:=true;

49                     a[i].v:=j;

50                 end;

51             inc(j);

52         end;

53 end;

54  

55 procedure dp;

56 var

57     i,j,k,l:longint;

58 begin

59     for i:=0 to n-1 do

60         for j:=1 to n-i do

61             for k:=1 to n do

62                 begin

63                     f[j,i+j,k]:=maxlongint;

64                     for l:=j to i+j do

65                         begin

66                             if a[l].v<k then down(f[j,i+j,k],f[j,l-1,k]+f[l+1,i+j,k]+s[i+j]-s[j-1]+p)

67                             else

68                                 begin

69                                     down(f[j,i+j,k],f[j,l-1,k]+f[l+1,i+j,k]+s[i+j]-s[j-1]+p);

70                                     down(f[j,i+j,k],f[j,l-1,a[l].v]+f[l+1,i+j,a[l].v]+s[i+j]-s[j-1]);

71                                 end;

72                         end;

73                 end;

74     ans:=maxlongint;

75     for i:=1 to n do down(ans,f[1,n,i]);

76     writeln(ans);

77 end;

78  

79 begin

80     init;

81     dp;

82 end.
View Code

 

你可能感兴趣的:(二叉查找树)