• [NOI2009]二叉查找树


    CVII.[NOI2009]二叉查找树

    首先该树的中序遍历是唯一可以确定的(直接按照数据值排序即可)。

    然后,因为权值可以被修改成一切实数,故我们完全可以把权值离散化掉。

    于是我们现在可以设置一个DP状态\(f[l,r,lim]\)表示:

    区间\([l,r]\)中的所有东西构成了一棵子树,且树中最小权值不小于\(lim\)的最优方案。

    然后就枚举根转移即可。转移的时候就可以看作是子树内所有东西被整体提高了一层,所以直接增加\(sum[l,r]\)(意为区间\([l,r]\)中的所有数据值之和)即可。同时,如果有当前枚举的根的权值不小于\(lim\),显然就可以不修改,但是两边儿子的权值就必须比它大;否则则必须修改,两边儿子的权值下限还是\(lim\)(因为根的权值可以被修改成一个略大于\(lim\)的实数)。

    则时间复杂度\(O(n^4)\)

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    int n,m,sum[110],f[110][110][110];
    struct dat{
    	int val,key,lam;
    }a[100];
    int dfs(int l,int r,int lim){
    	if(l>r)return 0;
    	if(f[l][r][lim]!=-1)return f[l][r][lim];
    	int &now=f[l][r][lim];now=0x3f3f3f3f;
    	for(int i=l;i<=r;i++){//assume that i is the root in the section [l,r].
    		if(a[i].key>=lim)now=min(now,dfs(l,i-1,a[i].key)+dfs(i+1,r,a[i].key)+sum[r]-sum[l-1]);//do not modify, the height simply increased by one.
    		now=min(now,dfs(l,i-1,lim)+dfs(i+1,r,lim)+m+sum[r]-sum[l-1]);//modify i to any real number a little greater than lim.
    	}
    	return now;
    }
    int main(){
    	scanf("%d%d",&n,&m),memset(f,-1,sizeof(f));
    	for(int i=1;i<=n;i++)scanf("%d",&a[i].val);
    	for(int i=1;i<=n;i++)scanf("%d",&a[i].key);
    	for(int i=1;i<=n;i++)scanf("%d",&a[i].lam);
    	sort(a+1,a+n+1,[](dat u,dat v){return u.key<v.key;});
    	for(int i=1;i<=n;i++)a[i].key=i;
    	sort(a+1,a+n+1,[](dat u,dat v){return u.val<v.val;});
    	for(int i=1;i<=n;i++)sum[i]=sum[i-1]+a[i].lam;
    	printf("%d\n",dfs(1,n,1));
    	return 0;
    }
    

  • 相关阅读:
    机器学习:逻辑回归(基础理解)
    机器学习:模型泛化(L1、L2 和弹性网络)
    机器学习:模型泛化(LASSO 回归)
    机器学习:模型泛化(岭回归:Ridge Regression)
    Numpy:np.random 的使用
    ASP.NET MVC 视图层-生成链接相关(Html.ActionLink,Url.Action)
    eval实例
    <a>实现按钮的javascript+jquery编程实例
    SQL Server之XML PATH()
    分页数算法
  • 原文地址:https://www.cnblogs.com/Troverld/p/14601251.html
Copyright © 2020-2023  润新知