【BZOJ】1564: [NOI2009]二叉查找树

传送门 http://www.lydsy.com/JudgeOnline/problem.php?id=1564

Solution

这题数据范围是 n70

首先,我们很容易看出这是个treap……
(先为看不出的默哀)

将3个值分别记为abc
按a排序后,treap构造只能由连续的一段点构成一棵子树
那么枚举左端点、右端点还有根的位置……
哎呀,怎么转移呢QwQ

发现这东西好像没法处理,那么就再加一维状态强上,表示根的权值不小于某个数

这样就可以通过枚举根的权值、左右端点和根完成转移
考虑价值的维护,首先是对根的权值进行了修改,这种情况在转移时可以处理
那么另一方面就是访问价值了,一个点的访问价值就是它的c叠加深度次。我们子树又是一层层合并的,那么只要每次合并子树的时候把子树内所有点c求个和加进总价值就好(前缀和)

枚举根的权值的时候分两种情况转移,一是修改根的权值,二是不修改

对b做个离散化先(懒得手写快排QwQ)

#include<stdio.h>
#include<algorithm>
#include<cstring>
#define For(i,a,b) for (int i=a;i<=b;i++)
#define A t[i].a
#define B t[i].b
#define C t[i].c
#define N 75
using namespace std;

struct T
{
    int a,b,c;
    friend bool operator < (T a,T b){return a.a<b.a;}
}t[N];

int st[N],S[N],f[N][N][N],n,K;

int main()
{
    scanf("%d%d",&n,&K);
    For(i,1,n) scanf("%d",&A);
    For(i,1,n) scanf("%d",&B),st[i]=B;
    For(i,1,n) scanf("%d",&C);
    sort(t+1,t+n+1);sort(st+1,st+n+1);
    For(i,1,n) B=lower_bound(st+1,st+n+1,B)-st;
    For(i,1,n) S[i]=C+S[i-1];
    memset(f,0x3f,sizeof(f));
    For(i,1,n+1) For(w,0,n) f[i][i-1][w]=0;
    for (int w=n;w;w--) for (int l=n;l;l--) For(r,l,n) For(i,l,r)
    {
        f[l][r][w]=min(f[l][r][w],f[l][i-1][w]+f[i+1][r][w]+K+S[r]-S[l-1]);
        if (w<=B) f[l][r][w]=min(f[l][r][w],f[l][i-1][B]+f[i+1][r][B]+S[r]-S[l-1]);
    }
    int ans=2033333333;
    For(i,0,n) ans=min(ans,f[1][n][i]);
    printf("%d",ans);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值