[BZOJ1564][NOI2009]二叉查找树 动态规划

这玩意儿就是一个Treap对吧
因为key值可以选择任意实数,所以修改之后的key值
F[l][r][w] 表示构建l到r的Treap并且根节点的key值为w所需要的最小代价
O(n3) 状态, O(n) 转移,总时间 O(n4)

/**************************************************************
    Problem: 1564
    User: di4CoveRy
    Language: C++
    Result: Accepted
    Time:472 ms
    Memory:5816 kb
****************************************************************/

#include <iostream>
#include <cstdio>
#include <algorithm>

#define N 105
#define INF (1<<29)

using namespace std;

struct Monster{ int tr,key,v; }Q[N];
int e[N],sum[N],vis[N][N][N];
int n,k;
inline void ut(int &x,int y) { x = min(x,y); }

bool cmpe(int p1,int p2) { return Q[p1].key < Q[p2].key; }
bool cmpq(Monster p1,Monster p2) { return p1.tr < p2.tr; }

int F(int l,int r,int w) {
    if (l > r) return 0;
    if (vis[l][r][w]) return vis[l][r][w];

    int ret = INF;
    if (l == r) return Q[l].key >= w ? Q[l].v : Q[l].v + k;
    for (int _=l;_<=r;_++) {
        ut(ret , F(l,_-1,w) + F(_+1,r,w) + (sum[r]-sum[l-1]) + k);
        if (w <= Q[_].key)
            ut(ret , F(l,_-1,Q[_].key) + F(_+1,r,Q[_].key) + (sum[r]-sum[l-1]) );
    }
    return vis[l][r][w] = ret;
}

int main() {
    scanf("%d%d",&n,&k);
    for (int _=1;_<=n;_++) scanf("%d",&Q[_].tr);
    for (int _=1;_<=n;_++) scanf("%d",&Q[_].key);
    for (int _=1;_<=n;_++) scanf("%d",&Q[_].v);

    for (int _=1;_<=n;_++) e[_] = _;
    sort(e+1,e+n+1,cmpe);
    for (int _=1;_<=n;_++) Q[ e[_] ].key = _;
    sort(Q+1,Q+n+1,cmpq);

    for (int _=1;_<=n;_++) sum[_] = sum[_-1] + Q[_].v;

    int ans = INF;
    for (int _=1;_<=n;_++) ut(ans,F(1,n,_));
    printf("%d\n",ans);
    return 0;
} 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值