2016 ICPC Hong Kong G Scaffolding —— 笛卡尔树上DP

202 篇文章 5 订阅
5 篇文章 0 订阅

This way

题意:

他这个题意稍微的不正确,它应该是放了这个竹子之后就到这个竹子上面(也许)。否则样例,题解和程序就不对了吧。

题解:

在这里插入图片描述
大致思路就是这样,我这里用dp代替了f,res代替了g。
sum表示子树的值的和,siz表示子树大小。
ll v=(a[x]-a[fa])*siz[x]-res[ls[x]]-res[rs[x]];
表示当前点把统治的区间内的所有点的高拆到和父亲一样高的时候,还需要拆几个(因为要减去儿子的贡献)
res[x]=dp[x]*m-sum[x]+a[fa]*siz[x];
表示这个点可以拆多少个,减去这个点需要拆多少个就是它对上面的贡献

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N=1e5+5;
ll dp[N],res[N],sum[N],siz[N],a[N];
int fa[N],ls[N],rs[N],st[N],top;
int n;
ll m;
void build(){
    for(int i=1;i<=n;i++){
        int f=0;
        while(top&&a[st[top]]>a[i])
            top--,f=1;
        if(top)fa[i]=st[top],rs[st[top]]=i;
        if(f)ls[i]=st[top+1],fa[ls[i]]=i;
        st[++top]=i;
    }
}
void dfs(int x,int fa){
    if(!x)return ;
    dfs(ls[x],x),dfs(rs[x],x);
    dp[x]=dp[ls[x]]+dp[rs[x]];
    sum[x]=sum[ls[x]]+sum[rs[x]]+a[x];
    siz[x]=siz[ls[x]]+siz[rs[x]]+1;
    ll v=(a[x]-a[fa])*siz[x]-res[ls[x]]-res[rs[x]];
    if(v>0)dp[x]+=(v+m-1)/m;
    res[x]=dp[x]*m-sum[x]+a[fa]*siz[x];
}
int main()
{

    scanf("%d%lld",&n,&m);
    for(int i=1;i<=n;i++)
        scanf("%lld",&a[i]);
    build();
    dfs(st[1],0);
    printf("%lld\n",dp[st[1]]);
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值