hdu6161Big binary tree-(树形dp+空间优化)

该博客介绍了如何解决HDU6161问题,通过树形动态规划和空间优化策略,计算经过某个节点的最长路径。关键在于理解节点的最大路径可能来自其子树的最值加节点值,或者从叶子节点沿着最大值路径到根节点。通过只记录受影响节点的值,并在搜索过程中动态计算,实现了空间复杂度为O(mlogn)的解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题解:经过这个点最长路径可能是这个点的左右子树的最大值得和加上这个点的值或者是以这个点为根下面叶子节点爬上来的最大值加上max(它往真正的根爬途中经过的结点的值加上另外一棵子树)

因为这个结点的值更新了只有影响到它上面那些节点的最大值所以只要把影响的那些节点的值记录一下,其他的结点的最大值根据它向下能向下几层向左取或者向右取就可以了。所以我们只要记录那些被影响的节点的值,其他的不记录到时候按照上面的方法搜索一下即可,这样空间复杂度就是0(mlogn)如果把每个值都记录的话这题空间不够

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<map>
#include<cstdio>
using namespace std;
typedef long long int ll;
#define lson 2*x
#define rson 2*x+1
map<int,ll>v;
map<int,ll>f;
int n,m;
int deep(int x){
    int ans = 0;
    while(x<=n){
        ans++;
        x *= 2;
    }
    return ans;
}
ll dp(int x){
    if(x>n) return 0;
    if(f.count(x))   return f[x];
    ll ans;
    if(v.count(x))
        ans = v[x];
    else
        ans = x;
    if(deep(rson)==deep(lson))
        ans += dp(rson);
    else
        ans += dp(lson);
    return ans;
}
ll search(int x){
    ll ans = dp(lson)+dp(rson);
    if(v.count(x))
        ans += v[x];
    else
        ans += x;
    if(x==1)
        return ans;
    ll sum = dp(x);
    int pre;
    while(x>1){
        pre = x;
        x /= 2;
        sum += v.count(x)?v[x]:x;
        if(pre&1)
            ans = max(sum+dp(lson),ans);
        else
            ans = max(sum+dp(rson),ans);
    }
    return max(ans,sum);
}
void change(int x,ll y){
    v[x] = y;
    f[x] = max(dp(lson),dp(rson))+y;
    x /= 2;
    while(x){
        f[x] = max(dp(lson),dp(rson));
        if(v.count(x))
            f[x]+=v[x];
        else
            f[x]+=x;
        x /= 2;
    }
}
int main(){
    char s[20];
    while(scanf("%d%d",&n,&m)!=EOF){
        f.clear();
        v.clear();
        while(m--){
            int x;
            ll y;
            scanf("%s%d",s,&x);
            if(s[0]=='q')
                printf("%I64d\n",search(x));
            else{
                scanf("%I64d",&y);
                change(x,y);
            }
        }
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值