Problem Link

有一棵 \(n\) 个点的完全二叉树(点 \(i\) 的父亲是 \(\lfloor i/2\rfloor\)),第 \(i\) 个点有 \(a_i\) 个苹果。现在有 \(m\) 个订单,每个订单只接受 \(u_i\) 到 \(v_i\) 路径上的苹果,保证 \(u_i\) 是 \(v_i\) 的祖先,并且最多只接受 \(c_i\) 个苹果,单价为 \(w_i\)。你可以把苹果任意分给订单,求最大可能收益。

\(n,m\le 5\times 10^5\)。


技巧:费用流转 Hall 定理

我会费用流!直接从每个订单向链上的点连边,源点向订单连容量为订单上限,费用为单价的边,点向汇点连容量为苹果数的边,跑最大费用流即可!\(m\log n\) 条边,这不乱冲

当然冲不过去。考虑模拟费用流(说白了就是贪心,但是由费用流可以清楚地证明正确性),即将所有订单按单价从大到小排序,每次流的时候尽量流满即可(注意到反向边没法流)。

怎么流呢?是一个比较清奇的想法:二分一个流量,然后用别的方法判断当前流量是否合法。具体地,我们可以使用 Hall 定理!

发现给每条边钦定好流量之后,判断合不合法,就是判断是否存在一个链到苹果的匹配(前者满配),对应到 Hall 定理就是是否对于任意多条链的并,它们对应位置上的苹果数之和大于等于这些链的需求之和。

进一步,若干条链的并形成若干个连通块,显然不同连通块可以分开算。

于是考虑枚举这个连通块的根 \(r\),那么就是看是否存在一个以 \(r\) 为根的连通块,其中链和大于苹果和则不合法。可以对于每条链 \((u,v)\) 满足 \(u\) 在 \(r\) 的子树内,在 \(v\) 上打一个 \(-c_i\) 的标记,对每个节点打一个 \(+a_i\) 的标记,那么合法当且仅当每个包含根的连通块权值和均 \(\ge 0\)。这个可以用一个简单的 dp 判断:每个 \(f\) 从子树之和转移过来,然后对 \(0\) 取 \(\min\)。

修改一条链只用判断它的 \(v\) 到 \(1\) 路径上的那些根是否合法,每个根也只用重新计算 \(v\) 祖先里的那些点,所以单次时间复杂度 \(O(\log^2 n)\),总复杂度(算上二分)\(O(m\log^3 n)\)。

过不去!然后发现这个二分完全没必要,对于每个根可以直接算出所允许的最大值取个 \(\min\) 即可。

具体地,在 \(v\) 不断往上更新时,如果发现当前节点的 \(f\) 大于 \(0\),则可以在此时将链选的权值 \(x\) 增加 \(f\)。理由是反正 \(f\) 都要对 \(0\) 取 \(\min\),并且如果 \(f\le 0\),那增大 \(x\) 必然减小 \(f\),欠的总是要还的,不如将来再加。

这样总时间复杂度就 \(O(m\log^2 n)\) 了。

点击查看代码
#include <bits/stdc++.h>
#define For(i,a,b) for(int i=a;i<=b;i++)
#define Rev(i,a,b) for(int i=a;i>=b;i--)
#define Fin(file) freopen(file,"r",stdin);
#define Fout(file) freopen(file,"w",stdout);
using namespace std;
const int N=1e5+5; typedef long long ll;
struct Node{int u,v,c,w;bool operator<(const Node& rhs)const{return w>rhs.w;}}O[N];;
int n,m,a[N]; ll f[N][18],g[N][18];
ll work(int o,int v){
ll res=0; int z=__lg(o);
for(int k=v;k>=o;k>>=1){
int k1=k<<1,k2=k<<1|1; k1>n&&(k1=0); k2>n&&(k2=0);
res+=max(0ll,f[k1][z]+f[k2][z]+a[k]-g[k][z]);
}
return res;
}
void update(int o,int v,ll x){
int z=__lg(o); g[v][z]+=x;
for(int k=v;k>=o;k>>=1){
int k1=k<<1,k2=k<<1|1; k1>n&&(k1=0); k2>n&&(k2=0);
f[k][z]=min(0ll,f[k1][z]+f[k2][z]+a[k]-g[k][z]);
}
assert(f[o][z]>=0);
}
void solve(){
cin>>n>>m; For(i,1,n) cin>>a[i];;
For(i,0,n) memset(f[i],0,sizeof(f[i])),memset(g[i],0,sizeof(g[i]));
For(i,1,m) cin>>O[i].u>>O[i].v>>O[i].c>>O[i].w;; sort(O+1,O+1+m);
ll ans=0;
For(i,1,m){
auto [u,v,c,w]=O[i];
ll x=c; for(int o=u;o;o>>=1) x=min(x,work(o,v));
ans+=x*w; for(int o=u;o;o>>=1) update(o,v,x);
}
cout<<ans<<'\n';
}
int main(){
ios::sync_with_stdio(0); cin.tie(0);
int T; cin>>T; while(T--) solve();
return 0;
}

【网络流,dp】Gym102220A Apple Business的更多相关文章

  1. 【树形dp】Apple Tree

    [poj2486]Apple Tree Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 10800   Accepted: 3 ...

  2. POJ3176-基础DP

    很基础的dp题.有一头奶牛想接尽量多的苹果,有w此移动机会. dp[i][w] = max(dp[i-1][w+1] + 能否吃到苹果 ,dp[i-1][w] + 能否吃到苹果)  //从上一分钟是否 ...

  3. The 13th Chinese Northeast Collegiate Programming Contest

    题解: solution Code: A. Apple Business #include<cstdio> #include<algorithm> #include<ve ...

  4. QDEZ集训笔记【更新中】

    这是一个绝妙的比喻,如果青岛二中的台阶上每级站一只平度一中的猫,差不多站满了吧 自己的理解 [2016-12-31] [主席树] http://www.cnblogs.com/candy99/p/61 ...

  5. 较具体的介绍JNI

    JNI事实上是Java Native Interface的简称,也就是java本地接口.它提供了若干的API实现了和Java和其它语言的通信(主要是C&C++).或许不少人认为Java已经足够 ...

  6. 更具体的描述JNI

    JNI事实上,Java Native Interface缩写,也就是说,java本地接口. 它提供了许多API实现和Java并与其他语言的沟通(主要C&C++). 也许很多人认为Java够劲. ...

  7. POJ2385--Apple Catching(动态规划)

    It is a little known fact that cows love apples. Farmer John has two apple trees (which are convenie ...

  8. 较详细的介绍JNI

    JNI其实是Java Native Interface的简称,也就是java本地接口.它提供了若干的API实现了和Java和其他语言的通信(主要是C&C++).也许不少人觉得Java已经足够强 ...

  9. BZOJ 1221: [HNOI2001] 软件开发【最小费用最大流】

    Description 某软件公司正在规划一项n天的软件开发计划,根据开发计划第i天需要ni个软件开发人员,为了提高软件开发人员的效率,公司给软件人员提供了很多的服务,其中一项服务就是要为每个开发人员 ...

  10. Distributing Custom Apps

    Distributing Custom Apps 分配自定义应用程序 November 10, 2020 2020年11月10日 Custom apps let you meet the unique ...

随机推荐

  1. 云原生时代,领域驱动设计思想(DDD)如何落地?

    摘要:随着数字化世界的持续演进,软件架构设计思想在碰撞中不断优化.云原生时代的到来,加速了行业对于领域驱动设计理念(Domain-Driven Design)的实践落地诉求. 本文分享自华为云社区&l ...

  2. vue2升级vue3: h、createVNode、render、createApp使用

    h.createVNode 杂乱笔记,凑合着看,不喜勿喷! h 函数是什么 h 函数本质就是 createElement() 的简写,作用是根据配置创建对应的虚拟节点,在vue 中占有极其重要的地位! ...

  3. JS遍历循环方法性能对比:for/while/for in/for of/map/foreach/every

    这周codeReview例会,又遇到map与foreach到底谁问题.单独图方便,我会选择用map一个函数搞定一切.但是从语义的角度来讲,如果只是单纯遍历,还是推荐选择foreach.其实formap ...

  4. QA团队基于DataLeap开放平台能力的数据测试实践

    背景 &痛点 随着生态体系扩展和业务发展,数据在业务中承担的决策场景越来越多样化,一部分数据已应用在资损.高客诉等高风险场景,因此对数据质量的要求,尤其是高风险场景的质量要求非常之高.但在保障 ...

  5. 创建一个基本的FastAPI应用程序

    Python 搭建 FastAPI 项目 要生成FastAPI项目的代码,你可以使用FastAPI的脚手架工具来快速创建一个基本的FastAPI应用程序. 以下是创建一个新的FastAPI项目的步骤: ...

  6. Docker 删除 images

    1 查看本地已用镜像文件 [root@localhost web]# docker images 2.删除镜像 Redis [root@localhost web]# docker rmi 59589 ...

  7. 负载均衡 SLB 健康检查异常

    负载均衡 SLB 健康检查异常,接口地址不能访问 接口地址的访问首先需要健康检查状态为正常. 如果接口没有"首页",需要提供一个可访问的controller

  8. Android RxJava 异常时堆栈信息显示不全(不准确),解决方案都在这里了

    现象 大家好,我是徐公,今天为大家带来的是 RxJava 的一个血案,一行代码 return null 引发的. 前阵子,组内的同事反馈说 RxJava 在 debug 包 crash 了,捕获到的异 ...

  9. VS2019 快速实现 C# 连接 MySQL 数据库并实现基本操作代码

    一.工具: Visual Studio 2019 MySQL 数据库 二.添加动态链接: Visual Studio 中选择项目-> 管理NuGet程序包(N) -> 然后在浏览里面搜索 ...

  10. ElementUI - <el-table> 表格 selection 设置的复选框禁止选中某些行

    https://blog.csdn.net/weixin_44198965/article/details/119026054